🤨

【Flutter】Freezedクラスのリストをソートする

に公開

Freezedで定義したカスタムデータモデル(id, name, age)のリストを対象に、id順や年齢順で切り替えて並べ替えられるUIをHooksを使ってサクッと実装してみます!

Freezedクラスの定義

今回はid,年齢,名前のデータのFreezedクラスを生成します。

import 'package:freezed_annotation/freezed_annotation.dart';

part 'model.freezed.dart';


class ApiModel with _$ApiModel{
  const factory ApiModel({
    required int id,
    required String name,
    required int age,
  }) = _ApiModel;
}

ソートするのはid順と年齢順にします。
今回はデモ用にAIにリストの中身を生成してもらいました。

List<ApiModel> model = [
  ApiModel(id: 1, name: '佐藤 花子', age: 18),
  ApiModel(id: 2, name: '鈴木 太郎', age: 25),
  /*省略*/
  ApiModel(id: 10, name: '吉田 彩香', age: 47),
];

ソートの処理

そもそもソートとは...

ソートとは並べ替えのとことを指し、バブルソートやクイックソートなどアルゴリズムとして一つの研究分野になっておりコンピュータサイエンスでは必ず学ぶ基礎のひとつです。
ただし、今回はアルゴリズムを一から実装するのではなくDartに備わっているsort()関数を使って、手軽に並び替え処理を行います。
例えば数字のリストなら..sort()で昇順に並び替えが可能です。

final numbers = [3, 1, 5, 2];
numbers.sort(); // → [1, 2, 3, 5]

今回は単純なソートではだめな理由は今回は ApiModel というカスタムクラス(名前・年齢などの情報を持つ)をリストにしているためmodel.sort()だけでは並び替えができません。

final model = [
  ApiModel(id: 1, name: '佐藤', age: 30),
  ApiModel(id: 2, name: '田中', age: 25),
];
model.sort(); // ❌ エラー!

実装

ソートの処理は..sort()で並べ替えができます。
List<int>だと..sort()で完了しますが前述の通り今回はリストの中に複数のデータが入ってる状態なので()の中にどのデータの順番に並べ替えるかを定義しないとエラーが出てしまいます。
今回はid順ではなく年齢順に並べ替えたいので以下のようにします。

final sortedModel = List<ApiModel>.from(model)..sort((a, b) => a.age.compareTo(b.age));

id順

年齢順

解説

Dartのsort()メソッドには、(a, b) => int という比較関数を渡すことができます。
この関数の戻り値は以下のような意味を持ちます。

  • a < b → -1
  • a == b → 0
  • a > b → 1
    今回は年齢(age)で並べたいのでこう書きます。
model.sort((a, b) => a.age.compareTo(b.age));

元の model リストを保持したまま、新しい並び順のリストを作りたい場合は List.from() を使います。

final sortedModel = List<ApiModel>.from(model)
  ..sort((a, b) => a.age.compareTo(b.age));

おまけ(id順と年齢順を切り替える)

三項演算子とSwitchコンポーネントを使って切り替えを行います。
falseの時はid順でtrueの時は年齢順にします。

final isChecked = useState(false);
final sortedModel = List<ApiModel>.from(model)
      ..sort((a, b) =>
          isChecked.value ? a.age.compareTo(b.age) : a.id.compareTo(b.id));
Switch(
    value: isChecked.value,
    onChanged: (value) {
        isChecked.value = value;
    },
),

id順

年齢順

まとめ

今回はFreezedで定義したデータをソートし、さらにUIから切り替える方法を紹介しました。
ちょっとしたデータ操作や動的な表示切り替えはFlutterで実用的なアプリを作る上で避けては通れません。
Freezedを使えば、安全かつ簡単にデータを扱えるので今後も積極的に使っていこうと思います!
時間があれば、filter機能やsearch機能との組み合わせもやってみたいですね。

ぽちぽちのつどい

Discussion