Home > Software engineering >  Sum List<Map> to get distinct list
Sum List<Map> to get distinct list

Time:11-25

I have a List<Map> that I need the IDs to be distinct in the list and obtain a cumulative value for each ID.

What I currently have works, but I was wondering if there is a cleaner way to do this?

My code:

List tagId = ['a', 'b'];
List oldList = [{'id': 'a', 'value': 1}, 
                {'id': 'a', 'value': 1}, 
                {'id': 'a', 'value': 1}, 
                {'id': 'a', 'value': 1},
                {'id': 'b', 'value': 1},
                {'id': 'b', 'value': 1}];
List newList = [];
  
  for(final i in tagId) {
    int totalValue = 0;
    for(final d in oldList){
      if(i == d['id']){
        totalValue  ;
      }
    }
    newList.add({'id': i, 'value': totalValue});
  }
  print(newList);

CodePudding user response:

I'm assuming that you wrote the tagList manually, you don't want to do that manually or from another unnecessary algorithm that will result in it.

If you need just access to the id and value, then you probably want to avoid an O(N^2) algorithm, I wrote an O(N) that might help for better performance:

  Map<String, int> map = {};
  for(int index = 0; index < oldList.length; index =1) {
    map[oldList[index]["id"]] = (map[oldList[index]["id"]] ?? 0)   oldList[index]["value"] as int;
  }
  
  print(map); // {a: 4, b: 2}

and if you need the same result then you can just add this:

  List<Map> asMapList = [];
  map.forEach((key, value) {
    asMapList.add({"id": key, "value": value});
  } ); 
  print(asMapList); // [{id: a, value: 4}, {id: b, value: 2}]

CodePudding user response:

You can also:

  1. Merge/reduce the array list elements into a single Map.
  2. Generate the list from the merged Map.
void main() {
  List tagId = ['a', 'b'];
  List<Map<String, dynamic>> oldList = [
    {'id': 'a', 'value': 1},
    {'id': 'a', 'value': 1},
    {'id': 'a', 'value': 1},
    {'id': 'a', 'value': 1},
    {'id': 'b', 'value': 1},
    {'id': 'b', 'value': 1}
  ];

  // reduce uses the first element as initialValue, so I added an empty map
  // as the initial value, to start merging from the second element (second element here, but it's your actual first element)
  final merged = ([{}]   oldList).reduce(
    (map, e) => map..[e['id']] = (map[e['id']] ?? 0)   (e['value'] ?? 0),
  );

  var mergedAsList =
      merged.keys.map((key) => {'id': key, 'value': merged[key]});

  print(mergedAsList); // Same output as yours
}

I made it enter image description here

  • Related