Skip to content

Add Iterable.groupBy #30376

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
srawlins opened this issue Aug 9, 2017 · 6 comments
Closed

Add Iterable.groupBy #30376

srawlins opened this issue Aug 9, 2017 · 6 comments
Labels
area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. core-2 library-core type-enhancement A request for a change that isn't a bug

Comments

@srawlins
Copy link
Member

srawlins commented Aug 9, 2017

Iterable.groupBy would be great!

(I'm opening a new issue, instead of re-opening #11159, because the discussion over there was largely about how it would be hard to do without Dart 2.0. I'm opening this issue in the context of Dart 2.0. If this is not the right workflow, we can re-open #11159, and close this.)

class Iterable<E> {
  Map<F, Iterable<E>> groupBy<F>(F Function(E) groupingFn);
}

Some examples:

["Aardvark", "Antelope", "Zebra", "Bison", "Alligator"].groupBy((e) => e[0]);
// ==> {"A": ["Aardvark", "Antelope", "Alligator"], "B": ["Bison"], "Z": ["Zebra"]}

[1,2,3,4,5,6,7,8,9].groupBy((e) => i % 4);
// ==> {0: [4, 8], 1: [1, 5, 9], 2: [2, 6], 3: [3, 7]}

{"Maine": ["Acadia"], "Missouri": [],
 "Montana": ["Glacier", "Yellowstone"], "Rhode Island": []}
    .groupBy((k, v) => v.isEmpty);
// ==> {true: [Entry("Missouri", []), Entry("Rhode Island", [])],
//      false: [Entry("Maine", ["Acadia"]), Entry("Montana", ["Glacier", "Yellowstone"])}

(That last one assumes we get an iterator over key/value pairs in Map (#7088) that yields Entry objects. But if its a List or a Pair or a Tuple, whatever.)

I think this is a useful method to have, and also it is expected from developers in other languages. Python2 has groupby; Ruby has Enumerable#group_by, Rust's itertools has GroupBy; It is not to be found in Go, JavaScript (so people use Underscore.js).

Java 8's Collectors has groupingBy which I think is very well thought out; it has a few overloaded variations (could implement similar things in Dart with named arguments), like including a "reduction operation", something like:

["Aardvark", "Antelope", "Zebra", "Bison", "Alligator"]
    .groupBy((e) => e[0], reduce: (grouping) => grouping.length);
// ==> {"A": 3, "B": 1, "Z": 1}

Probably unnecessary in Dart, as we have other first class functional means, especially if Map gets a map function (#9590):

["Aardvark", "Antelope", "Zebra", "Bison", "Alligator"]
    .groupBy((e) => e[0]).map(grouping) => grouping.length);
// ==> {"A": 3, "B": 1, "Z": 1}
@srawlins srawlins added the area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. label Aug 9, 2017
@lrhn
Copy link
Member

lrhn commented Aug 10, 2017

I'd type it as Map<K,List<E>> groupBy<K>(K key(E element)) (that is, a map to lists, not iterables).
You have to go through the entire iterable before you can return a map because you don't know the keys before that. At that point, you will have collected and distributed all the values anyway, so there is no reason to use an Iterable for the values in the map.

@lrhn lrhn added library-core type-enhancement A request for a change that isn't a bug labels Aug 10, 2017
@floitschG floitschG added core-2 and removed core-m labels Aug 14, 2017
@floitschG
Copy link
Contributor

We then also need a Stream.groupBy -> Future<Map<K, List<T>>.

@rkj
Copy link

rkj commented Jun 20, 2018

+1 for this, seems Flutter went ahead and added it: https://docs.flutter.io/flutter/package-collection_collection/groupBy.html
could this at least be moved into quiver?

@matanlurey
Copy link
Contributor

@rkj: This is just normal package:collection:
https://pub.dartlang.org/documentation/collection/latest/collection/groupBy.html

@leafpetersen @lrhn feel free to re-open if you still plan to do this.

@vukisoft
Copy link

This would still be useful as using a top level groupBy breaks the fluent method calls.

groupBy(list.map(..).where(..), (item) => ..)
vs
list.map(..).where(..).groupBy((item) => ..)

@mraleph
Copy link
Member

mraleph commented Nov 26, 2019

@vukisoft note that you can now use static extension methods if you want to achieve fluent method calls.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. core-2 library-core type-enhancement A request for a change that isn't a bug
Projects
None yet
Development

No branches or pull requests

8 participants