I have a list of custom objects that I want to group based on some values within the object. My code basically looks like this:
class Bar{
String someVal;
int num; // group by this value
Bar(this.someVal, this.num);
}
class Foo{
String someVal;
List<Bar> bars;
Foo(this.someVal, this.bars);
}
void main()
{
Bar bar1 = Bar("val1", 3);
Bar bar2 = Bar("val2", 5);
Bar bar3 = Bar("val3", 2);
Foo foo1 = Foo("someString", [bar1, bar2, bar3]);
Bar bar4 = Bar("val4", 2);
Bar bar5 = Bar("val5", 3);
Bar bar6 = Bar("val6", 1);
Foo foo2 = Foo("someString", [bar4, bar5, bar6]);
List<Foo> foos = [foo1, foo2];
// Desired result: explicit groups by attribute 'num' in Bar
List<Map> groupedBars =
[{"num": 3, "bar": [bar1, bar5]},
{"num": 2, "bar":[bar3, bar4]},
{"num": 1, "bar": [bar6]}
];
}
How to get these groups efficiently without looping multiple times over these nested structures? Thanks for your help!
CodePudding user response:
Does this help?
//Get all bars out of the foos list
final bars = foos.map((foo) => foo.bars).expand((bars) => bars);
//Get all unique numbers out of the list of bars
final nums = bars.map((bar) => bar.num).toSet();
//Create the desired map by finding the bars that match num
final desiredMap= nums.map((num) => {
"num" : num,
"bar" : bars.where((bar) => bar.num == num).toList()
});
CodePudding user response:
This should work
List<Map> groupMyBars(List<Foo> myFoos) {
Map<int, List<Bar>> groupedBarsMap = {};
for (var foo in myFoos) {
for (var bar in foo.bars) {
groupedBarsMap.update(bar.num, (value) => [...value, bar], ifAbsent: () => [bar]);
}
}
return groupedBarsMap.keys.fold<List<Map>>(
[], (previousValue, element) => previousValue..add({"num": element, "bar": groupedBarsMap[element]}));
}