Home > Software design >  Sort a map within a map and convert to list within a list
Sort a map within a map and convert to list within a list

Time:02-14

Here's my data in Firebase:

prices
  price1
    priceAmount1: 10
    priceAmount2: 20
    priceAmount3: 30
  price2
    priceAmount1: 15
    priceAmount2: 5
    priceAmount3: 7
  price3
    priceAmount1: 2
    priceAmount2: 4
    priceAmount3: 6

If I straight away retrieve it. Sometimes the ordering is price2, price3, price1. So I tried sorting it like this:

      var sortedKeys = prices!.price!.keys.toList()..sort();
      for (var it = 0; it < sortedKeys.length; it  ) {
        print('${sortedKeys[it]}');
      }

But since it becomes a list, I'm not able to access the map anymore. I wanted to sort the map within a map then store it in a list within a list. Please help. Thanks!

Edit:

final splayByPrice =
    SplayTreeMap<dynamic, dynamic>((a, b) => a.compareTo(b));

List<Map<dynamic, dynamic>> priceAmountMap = [
        {
          'priceAmount1': 10,
          'priceAmount2': 20,
          'priceAmount3': 30,
        },
        {
          'priceAmount1': 15,
          'priceAmount2': 5,
          'priceAmount3': 7,
        },
        {
          'priceAmount1': 2,
          'priceAmount2': 4,
          'priceAmount3': 6,
        }
      ];

      Map<dynamic, Map<dynamic, dynamic>> priceMap = {
        'price2': priceAmountMap[1],
        'price1': priceAmountMap[0],
        'price3': priceAmountMap[2],
      };

      priceMap.forEach((key, value) {
        splayByPrice.addAll(value);
      });

      priceMap.forEach((key, value) {
        print('$key \t $value');
      });

What it prints, is still not sorted.

price2   {priceAmount1: 15, priceAmount2: 5, priceAmount3: 7}
price1   {priceAmount1: 10, priceAmount2: 20, priceAmount3: 30}
price3   {priceAmount1: 2, priceAmount2: 4, priceAmount3: 6}

CodePudding user response:

Dart's default Map implementation is a LinkedHashMap that stores entries in order of insertion.

(You haven't provided code that clearly shows your data structure, so I'll use my own example.)

If you want the Map to be sorted by the keys' alphabetic order, then you could:

  • Create a new Map, adding items to it in the desired order:

    var theMap = {
      4: 'four',
      7: 'seven',
      6: 'six',
      9: 'nine',
      5: 'five',
      1: 'one',
      8: 'eight',
      0: 'zero',
      3: 'three',
      2: 'two',
    };
    
    void main() {
      var sortedKeys = theMap.keys.toList()..sort();
      var sortedMap = {
        for (var key in sortedKeys)
          key: theMap[key]!,
      };
      print(sortedMap);
    }
    
  • Update the existing Map, removing and re-adding items in the desired order:

    void main() {
      var sortedKeys = theMap.keys.toList()..sort();
      for (var key in sortedKeys) {
        var value = theMap[key]!;
        theMap.remove(key);
        theMap[key] = value;
      }
      print(theMap);
    }
    
  • Use a SplayTreeMap, which keeps entries sorted by a comparison rule.

    import 'dart:collection'; 
    
    void main() {
      var splayTreeMap = SplayTreeMap.of(theMap);
      print(splayTreeMap);
    }
    

If you need to sort the data only once, I'd use one of the first two methods. If you're frequently adding new entries, then I'd use a SplayTreeMap instead of a Map/LinkedHashMap so that entries are kept in a sorted order. (But note that lookups, insertions, and removals in a SplayTreeMap are O(log n) instead of O(1).)

Also, if you're sorting strings that contain numbers, you probably don't want to use the normal string sort.

  • Related