Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sort a Map of Objects by Their Key Value

Tags:

dart

I have a JSON object that I need to it sort by value of the key "SortOrder" but I am not sure how to do this in Dart.

JSON:

"BTS": {
      "Id": "2039",,
      "SortOrder": "10001",
    },
"ETS": {
      "Id": "1039",,
      "SortOrder": "50",
    },
"RTS": {
      "Id": "39",,
      "SortOrder": "1",
    },
"TTS": {
      "Id": "139",,
      "SortOrder": "1001",
    },

What is the correct way to sort these objects by their "SortOrder" key value?

like image 466
Claude Avatar asked Jul 08 '18 20:07

Claude


People also ask

How do you sort a Map by key value?

Step 1: Create a TreeMap in java with a custom comparator. Step 2: Comparator should compare based on values and then based on the keys. Step 3: Put all key-value pairs from the hashmap into the treemap. Step 4: return the treemap.

Can we sort Map based on key?

Using TreeMap (putAll method) The idea is to put all data of HashMap into a TreeMap. The TreeMap follows Red Black Tree based implementation. The map is sorted according to the natural ordering of its keys.


2 Answers

A shorter version of Jonah Williams' approach:

var newMap = Map.fromEntries(originalMap.entries.toList()..sort((e1, e2) =>
    int.parse(e1.value["SortOrder"]).compareTo(int.parse(e2.value["SortOrder"]))));

If efficiency is important, it's probably a good idea to parse the "SortOrder" strings to integers only once, or use a string comparison that does numerical comparison on embedded numbers, like compareNatural from package:collection. With that, the code would be:

var newMap = Map.fromEntries(originalMap.entries.toList()..sort((e1, e2) =>
    compareNatural(e1.value["SortOrder"], e2.value["SortOrder"])));
like image 197
lrn Avatar answered Sep 22 '22 21:09

lrn


The default {} Dart maps is not ordered, and the ordered map SplayTreeMap is ordered by key and not value. In order to sort your list of objects, I would recommend slightly transforming them locally (if the label is significant).

 Map<String, <Map<String, String>>> objects = { /* data */ };
 List<Map<String, String>> objectList = objects.entries.map((entry) {
   return {
     'key': entry.key,
     // if you don't turn the order back to an int it will order them lexicographically.
     'sortOrder:': int.parse(entry.value['sortOrder']),
   };
 }).toList(); 

You can now sort this list using a custom comparator. The sort method modified the list in place.

objectList.sort((left, right) {
  return left['sortOrder'].compareTo(right['sortOrder']);
});

If you turn this list back into a map, you won't be able to guarantee that they remain in the correct order if you add new values. But by default the {} map (LinkedHashMap) preserves the insertion order.

final Map<String, Map<String, String>> sortedMap = {};
for (var entry in objectList) {
  sortedMap[entry['key']] = objects[entry['key']);
}
like image 38
Jonah Williams Avatar answered Sep 22 '22 21:09

Jonah Williams