ilmirfan
ilmirfan

Reputation: 27

Summarize List<Map<String,dynamic> elements

I have a sales List like below:

 List<Map<String,dynamic>> sales = [
    {'paid': 2000, 'name': 'person1'},
    {'paid': 2500, 'name': 'person2'},
    {'paid': 5600, 'name': 'person1'},
    {'paid': 974.0, 'name': 'person2'},
  ];

I want to sum persons' paid amount and show in a ListView.builder like below:

person1 : 7600 person2 : 3474

I need a hand with how to calculate every individual person inside a map in Dart/Flutter.

Thanks in advance.

Upvotes: 0

Views: 983

Answers (3)

Hayi Nukman
Hayi Nukman

Reputation: 1201

There is another way to do it. Following the method used on this answer, with some additional changes into the logic:

void main() {
  List<Map<String, dynamic>> sales = [
    {'paid': 2000, 'name': 'person1'},
    {'paid': 2500, 'name': 'person2'},
    {'paid': 5600, 'name': 'person1'},
    {'paid': 974.0, 'name': 'person2'},
  ];
  var result = sales.groupBy((m) => m['name']).map(
        (key, value) => MapEntry(
          key,
          value.fold<double>(0.0, (a, b) => a + b['paid']),
        ),
      );
  print(result);
}

// use this extension
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));
}

it will produce something like this:

{person1: 7600.0, person2: 3474.0}

You can try to run it on dartpad.

Upvotes: 1

Me&#239; M.
Me&#239; M.

Reputation: 321

I would go with a method a bit more verbose but that would allow you top keep a reference on your results.

  final List<Map<String, dynamic>> sales = [
    {'paid': 2000, 'name': 'person1'},
    {'paid': 2500, 'name': 'person2'},
    {'paid': 5600, 'name': 'person1'},
    {'paid': 974.0, 'name': 'person2'},
  ];

  final salesByName = <String, List<Map<String, dynamic>>>{};
  
  for (final entry in sales) {
    if (salesByName.keys.contains(entry["name"] as String)) {
      salesByName[entry["name"] as String]?.add(entry);
    } else {
      salesByName[entry["name"] as String] = [entry];
    }
  }

  final salesByNameSum = <String, double>{};

  for (final name in salesByName.entries) {
    print("${name.key} has ${name.value.length} entries");
    double sum = 0.0;
    for (final sale in name.value) {
      sum += sale['paid'] as double;
    }
    salesByNameSum[name.key] = sum;
  }

  for (final entry in salesByNameSum.entries) {
    print('${entry.key}: ${entry.value}');
  }

You would first create a map using name as a key and containing a list of sales maps in its value. That way you can easily access the list of each person's transactions.

Then, you could create another smaller map, containing exclusively the name as its key, and the sum as its value.

Here is a pure-dart DartPad as an example : https://dartpad.dev/?id=2f4e9b102ba931846bc8734c1180b29f

Hope it helps!

Upvotes: 2

tareq albeesh
tareq albeesh

Reputation: 1861

this code might help you:

   void main() {
      List<Map<String, dynamic>> sales = [
        {'paid': 2000, 'name': 'person1'},
        {'paid': 2500, 'name': 'person2'},
        {'paid': 5600, 'name': 'person1'},
        {'paid': 974.0, 'name': 'person2'},
      ];
    
      Map map = Map();
      for (var sale in sales) {
        if (map.keys.contains(sale['name'])) {
          map[sale["name"]] = map[sale["name"]] + sale['paid'];
        } else
          map[sale["name"]] = sale['paid'];
      }
      print(map.toString());
    }

where the output would be:

{person1: 7600, person2: 3474.0}

Upvotes: 1

Related Questions