本記事は下記リンクのDark公式ページのチュートリアルを学習したメモです。

Iterable collections

コレクション(Collection)とは

前回のDart Basicシリーズで言及したもので一般的には次のものをいう。

  • List:インデックスによって要素を参照することができる。配列に近い。
  • Set:Listと似ているが、同一要素は1つだけになる。
  • Map:キーによって要素を参照することができる。

イテラブル(Iterable)とは

Iterableは、順番にアクセスできる要素のコレクションだ。

Iterableは抽象クラスで直接インスタンス化することはできないが、新しいList、Setなどを作成することで新しいIterableを作成できる。

List、Set両方、Iterable具現化(implements)していてIterableクラスと同じメソッドとプロパティを持つ。

Mapは異なるデータ構造であるが、キーまたは要素を使ってIterableオブジェクトを作成できる。

IterableはListのように[]を使えないのでelementAtメソッドを使う。

DartPad

1
2
3
4
void main() {
  Iterable<int> iter = [1, 2, 3];
  print('First: ${iter.elementAt(0)}');
}
1
First: 1

要素の参照

For-in

IterableなオブジェクトはFor-inループにて反復参照できる。

1
2
3
4
5
6
void main() {
  const iter = ['Salad', 'Popcorn', 'Toast'];
  for (final element in iter) {
    print(element);
  }
}
1
2
3
Salad
Popcorn
Toast

first, last

Iterableクラスでは[]を使えないが、first、lastプロパティを使って最初の要素、最後の要素を参照できる。

1
2
3
4
5
void main() {
  Iterable<String> iter = const ['サラダ', 'ポップコーン', 'トースト'];
  print('最初の要素は${iter.first}です。');
  print('最後の要素は${iter.last}です。');
}
1
2
最初の要素はサラダです。
最後の要素はトーストです。

Iterableはインスタンス化できないと言ってなかった?翻訳機が悪い?

firstWhere

先ほどの例は最初の要素を参照しているが、firstWhereを使って条件を満たす最初の要素を参照することもできる。

firstWhereはパラメータとして関数を渡す必要があり、その関数でtrueを渡すと条件を満たすことになる。

次のコードはfirstWhereを使ういくつかの方法だ。最後の例は条件を満たさなかった場合どうするかを指定する例である。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
bool predicate(String item) {
  return item.length > 5;
}

void main() {
  const items = ['Salad', 'Popcorn', 'Toast', 'Lasagne'];
  
  var foundItem1 = items.firstWhere((item) => item.length > 5);
  print(foundItem1);
  
  var foundItem2 = items.firstWhere((item) {
    return item.length > 5;
  });
  print(foundItem2);
  
  var foundItem3 = items.firstWhere(predicate);
  print(foundItem3);
  
  var foundItem4 = items.firstWhere(
    (item) => item.length > 10,
    orElse: () => 'None!',
  );
  print(foundItem4);
}
1
2
3
4
Popcorn
Popcorn
Popcorn
None!

firstWhereで条件に満たす要素がない場合、StateErrorが発生する。要素がわからない場合はorElseを使うのを習慣にした方が良いかもしれない。

any, every

firstWhereは条件を満たす最初の要素のみであるが、全ての要素を検査したくなるかもしれない。なるかな。ならないかな。

any、everyをそのときに使える。

  • any:少なくとも1つの要素が条件を満たしたときにtrueを返却する。
  • every: 全ての要素が条件を満たした場合にtrueを返却する。
1
2
3
4
5
6
7
8
9
10
11
void main() {
  const items = ['Salad', 'Popcorn', 'Toast'];

  if (items.any((item) => item.contains('a'))) {
    print('At least one item contains "a"');
  }

  if (items.every((item) => item.length >= 5)) {
    print('All items have length >= 5');
  }
}
1
2
At least one item contains "a"
All items have length >= 5

where

firstWhereは条件を満たす最初の一つの要素を返却するが、条件を満たす全ての要素が欲しいときにはwhereを使う。

1
2
3
4
5
6
7
8
9
10
11
12
13
void main() {
  const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
  
  // 偶数のみ選択
  var evenNumbers = numbers.where((number) => number.isEven);
  print(evenNumbers);
  
  // 20超えるの数字
  var overTwenty = numbers.where((number) => number > 20);
  if (overTwenty.isEmpty) {
    print('20を超える数字はありません。');
  }
}
1
2
(2, 4, 6, 8, 10)
20を超える数字はありません。

map

whereは条件を満たす要素を返却した。mapは全ての要素に指定の処理結果を返却する。

1
2
3
4
5
6
7
8
9
10
void main() {
  const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
  
  // 偶数のみ選択
  var evenNumbers = numbers.where((number) => number.isEven);
  print(evenNumbers);
  
  var enMinusOne = evenNumbers.map((number) => number - 1);
  print(enMinusOne);
}
1
2
(2, 4, 6, 8, 10)
(1, 3, 5, 7, 9)

最後に

Flutter Introduction記事を見た人は気づいているかもしれないが、この記事のmapを使う場面がある。注意して欲しいのはこの記事で説明したwhere、mapなどの機能はIterableで返却する。なのでListで返却したい場合はtoListをつける。

タグ:

カテゴリー:

更新日時:

コメントする