Home > Software design >  Like "GROUP BY" SQL function - structure in Dart for List of Maps
Like "GROUP BY" SQL function - structure in Dart for List of Maps

Time:06-26

i want to group data and summarize one value (ctd), this is my data:

var data = [
  {"day": 'Monday', "weather": 'warm', 'ctd': 20, 'other':'a'},
  {"day": 'Monday', "weather": 'warm', 'ctd': 15, 'other':'b'},
  {"day": 'Tuesday', "weather": 'cold', 'ctd': 25, 'other':'c'},
  {"day": 'Tuesday', "weather": 'cold', 'ctd': 35, 'other':'d'},
];

The result i want is this:

  var result = [
    {"day": 'Monday', "weather": 'warm', 'ctd': 35},
    {"day": 'Tuesday', "weather": 'cold', 'ctd': 60},
  ];

In SQL i would write something like

  SELECT day, weather, sum(ctd) as ctd FROM data GROUP BY day, weather

but in Dart i dont get how to accomplish this, i tried with groupBy and fold, but a get a map, and can do only with one key or field.

  import 'package:collection/collection.dart';
  ///...
  var result = groupBy(data, (Map obj) => obj['day']).map((key, value) =>
        MapEntry(key, value.fold<int>(0, (p, e) => p   (e['ctd'] as int))));
  print(result); // {Monday: 35, Tuesday: 60}

I suspect that the answer is simple, but after having read other answers I can't find it, or I can't imagine it

The most likely question (is not the same) in stack overflow is this Flutter/Dart how to groupBy list of maps where i find how to use the groupBy

CodePudding user response:

Use package:fast_immutable_collections to turn your day and weather into a two element IList, which can be used as a map key, and then do your data reduction as you did before.

CodePudding user response:

An approach like this can be generalized and improved, but this is a starting point that works:

import 'dart:collection';

List<Map<String, Object>> groupBy(List<Map<String, Object>> list) {
  
  LinkedHashMap<String, Map<String, Object>> lmap = LinkedHashMap();
  for (var map in list) {
    if (lmap[(map['day'] as String)   (map['weather'] as String)] == null) {
      lmap[(map['day'] as String)   (map['weather'] as String)] = map;
    } else {
      var t = lmap[(map['day'] as String)   (map['weather'] as String)]!;
      t['ctd'] = (t['ctd'] as int)   (map['ctd'] as int);
    }
  }
  return lmap.entries.map((entry) => entry.value).toList();
}

void main() {
  var data = [
    {"day": 'Monday', "weather": 'warm', 'ctd': 20, 'other': 'a'},
    {"day": 'Monday', "weather": 'warm', 'ctd': 15, 'other': 'b'},
    {"day": 'Tuesday', "weather": 'cold', 'ctd': 25, 'other': 'c'},
    {"day": 'Tuesday', "weather": 'cold', 'ctd': 35, 'other': 'd'},
  ];
  print(groupBy(data));
}
  • Related