[Flutter/dart]Mapの要素の並び替えや抽出
概要
Flutterでのアプリ作成において、僕はユーザデータなどをMapで保持することが多いです(listだとデータを削除したときのindexのずれへの対応が面倒なため)。その場合、データを画面上に表示する際に、順番を規定したり特定の条件のデータだけを取り出したりするには一工夫必要です。(C#のdictionaryはlistと同じように扱えるのにな、、、)
方法
MapをMapEntryのlistに変換すればwhereやsortなどのメソッドが使えます。あとは使う側(基本的にはWidgetのbuildのはず)で引数をList<MapEntry>に取ればよい。
並び替え
以下では複数の並び替え方法に対応できるように比較方法をデリゲートで渡すメソッドにしています。
class UserData{
String name;
int score;
UserData({this.name, this.score});
}
class MyHomePageState extends State<MyHomePage> {
Map<int, UserData> data;
@override
void initState() {
data={
0: UserData(name: "Alice", score: 90),
1: UserData(name: "Bob", score: 87),
2: UserData(name: "Charlie", score: 98),
};
}
@override
Widget build(BuildContext context) {
//scoreの低い順に並び替え
var _entries=_orderData(data, (a, b) => (a.value as
UserData).score.compareTo((b.value as UserData).score));
return Scaffold(
appBar: AppBar(
title: Text('demo'),
),
body: Container(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: _entries.map((e) => ListTile(
title: Text(
"${e.value.name}: ${e.value.score}",
style: TextStyle(
fontSize: 16
),
),
)).toList(),
)
)
);
}
//これ!
List<MapEntry> _orderData(Map<int, dynamic>maps, int
Function(MapEntry<int, dynamic>, MapEntry<int, dynamic>) sorter){
return maps.entries.toList()..sort((a, b)=> sorter(a, b));
}
}
抽出
同じく条件を表すデリゲートを引数にしたメソッドを作ります。
List<MapEntry> _selectData(Map maps, bool Function(MapEntry) predicate){
return maps.entries.toList().where((element) =>
predicate(element)).toList();
}
@override
Widget build(BuildContext context) {
//scoreが90以上のデータを抽出
var _entries=_selectData(data, (e) => e.value.score>90);
return Scaffold(
appBar: AppBar(
title: Text('demo'),
),
body: Container(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: _entries.map((e) => ListTile(
title: Text(
"${e.value.name}: ${e.value.score}",
style: TextStyle(
fontSize: 16
),
),
)).toList(),
)
)
);
}
最後に
個人としては、データ保持は検索や削除のしやすさを考えてMap、widgetに一覧表示する場合は並び替えや条件抽出のしやすさを考えてList<MapEntry>を使っています(あくまで個人的な手法ですが)。
最新記事
すべて表示やりたいこと TextFieldで入力フォームを作りたい。 例えば入力内容が金額の場合、3桁区切りで頭に¥を付けた表記にしたい。 ただしユーザにこれらを入力させるのではなく、ユーザはあくまで数字を入力するだけで、アプリ側で自動でフォーマットしたい。 方法...
現象 やってること iosシミュレータで画像をデバイスのローカルに保存 保存したパスをデータベースに保存 アプリ立ち上げ時にデータベースから画像パスを取得し、そのパスの画像を画面上に表示 起きている現象 iosシミュレータを再起動した場合、上記3で「ファイルパスが見つからな...
やりたいこと 初期値さえ決まればあとは不変な変数がある ただし、コンストラクタ起動時にはまだ決定できない このような変数について late finalで変数を定義 (何らかのタイミングで)初期化されたかどうかをチェックし、されていなければ値を入れる(チェックしないとfina...
Comments