Flutter/Dart how to groupBy list of maps

Gui*_*ume 6 dart flutter

I have this list of maps.

[
    {title: 'Avengers', release_date: '10/01/2019'},
    {title: 'Creed', release_date: '10/01/2019'}
    {title: 'Jumanji', release_date: '30/10/2019'},
]
Run Code Online (Sandbox Code Playgroud)

I would like to write a code that would group the list of movies by release_date like that.

[
    {'10/01/2019':  [
                  {title: 'Avengers'},
                  {title: 'Creed'}
              ]
  },

   {'30/10/2019': [
                  {title: 'Jumanji'}
              ]
 }
]
Run Code Online (Sandbox Code Playgroud)

AWh*_*ord 36

如果你有Dart 2.7,你可以扩展 Iterable添加一个有用的groupBy方法:

extension Iterables<E> on Iterable<E> {
  Map<K, List<E>> groupBy<K>(K Function(E) keyFunction) => fold(
      <K, List<E>>{},
      (Map<K, List<E>> map, E element) =>
          map..putIfAbsent(keyFunction(element), () => <E>[]).add(element));
}
Run Code Online (Sandbox Code Playgroud)

现在,您是List of Maps,可以使用以下内容进行分组:

final releaseDateMap = listOfMaps.groupBy((m) => m['release_date'])
Run Code Online (Sandbox Code Playgroud)

像这样的数据:

[
    {title: 'Avengers', release_date: '10/01/2019'},
    {title: 'Creed', release_date: '10/01/2019'}
    {title: 'Jumanji', release_date: '30/10/2019'},
]
Run Code Online (Sandbox Code Playgroud)

会变成:

{
  '10/01/2019': [
    {title: 'Avengers', release_date: '10/01/2019'},
    {title: 'Creed', release_date: '10/01/2019'}
  ],
  '30/10/2019': [
    {title: 'Jumanji', release_date: '30/10/2019'},
  ]
}
Run Code Online (Sandbox Code Playgroud)

  • @FaizanMubasher,您也可以以与自定义对象相同的方式使用它。例如 `final lastNameMap = listOfPeople.groupBy((person) =&gt; person.lastName);` (2认同)

att*_*ona 17

集合实现该groupBy功能。

对于按日期分组:

import "package:collection/collection.dart";

main(List<String> args) {
  var data = [
    {"title": 'Avengers', "release_date": '10/01/2019'},
    {"title": 'Creed', "release_date": '10/01/2019'},
    {"title": 'Jumanji', "release_date": '30/10/2019'},
  ];


  var newMap = groupBy(data, (obj) => obj['release_date']);

  print(newMap);
}
Run Code Online (Sandbox Code Playgroud)

release_date要从每个地图条目中删除密钥:

var newMap = groupBy(data, (obj) => obj['release_date']).map(
    (k, v) => MapEntry(k, v.map((item) { item.remove('release_date'); return item;}).toList()));
Run Code Online (Sandbox Code Playgroud)

更改密钥:

var newMap = groupBy(data, (obj) => obj['release_date']).map(
    (k, v) => MapEntry(k, v.map((item) => {'name': item['title']}).toList()));
Run Code Online (Sandbox Code Playgroud)

  • 请注意,这个“groupBy”不是 [`dart:collection`](https://api.dart.dev/stable/2.7.1/dart-collection/dart-collection-library.html) 的一部分——这个引用[第三方集合](https://pub.dartlang.org/packages/collection)包。 (11认同)
  • 从“collection 1.15.0-nullsafety.4”开始,您可以将其替换为“data.groupListsBy((obj) =&gt; ...)”。https://github.com/dart-lang/collection/blob/1.15.0/lib/src/iterable_extensions.dart#L389 (2认同)

小智 7

我不知道为什么没有人提到如何通过基本的内置函数和方法来实现它,例如:

main() {
  List<Map> data = [
    {'title': 'Avengers', 'release_date': '10/01/2019'},
    {'title': 'Creed', 'release_date': '10/01/2019'},
    {'title': 'Jumanji', 'release_date': '30/10/2019'},
  ];

  // Loop through empty {} map and check if the release date exists, if not
  // add as the key and empty list as the value, then fill the list with element
  // itself, removing 'release_date' before adding. Then you can map the map
  // to a list of maps.
  List result = data
      .fold({}, (previousValue, element) {
        Map val = previousValue as Map;
        String date = element['release_date'];
        if (!val.containsKey(date)) {
          val[date] = [];
        }
        element.remove('release_date');
        val[date]?.add(element);
        return val;
      })
      .entries
      .map((e) => {e.key: e.value})
      .toList();

  print(result);
}
Run Code Online (Sandbox Code Playgroud)

输出:

C:\Users\duoqu\Desktop>dart run test.dart
[{10/01/2019: [{title: Avengers}, {title: Creed}]}, {30/10/2019: [{title: Jumanji}]}]
Run Code Online (Sandbox Code Playgroud)