12

I want to sort a Map<String,int> by values.

{'201': 4, '2017CS197': 2, '2017CS300': 6, '202': 4, '205': 3, '206': 3, '207': 5}

this is my map.

after i want to get result as {'2017CS300': 6,'207':5,'202':4,'201':4,'206':3,'205':3,'2017CS197':2}

Thank You!

jamesdlin
  • 81,374
  • 13
  • 159
  • 204
awpathum
  • 227
  • 4
  • 13

4 Answers4

18

The default map class is insertion-ordered on the keys. The easiest approach is to just create a new map with the same entries, added in the order you want. First, let's find the order you want:

var sortedEntries = map.entries.toList()..sort((e1, e2) {
  var diff = e2.value.compareTo(e1.value);
  if (diff == 0) diff = e2.key.compareTo(e1.key);
  return diff;
});

(This assumes that your keys and values are all Comparable, otherwise you need to figure out how to compare them yourself. In this particular case, where keys are Strings and values are ints, it's only null keys or values that may be incomparable).

This orders the entries in reverse value order, and for equal values, in reverse key order.

You can then create a new map from those entries:

var newMap = Map<String, int>.fromEntries(sortedEntries);

or you can modify the existing map by removing the old entries and adding the new:

map..clear()..addEntries(sortedEntries)

or

for (var entry in sortedEntries) {
  map..remove(entry.key)..[entry.key] = entry.value;
}

There is no functionality on the map class itself to order its entries.

lrn
  • 64,680
  • 7
  • 105
  • 121
  • Your code is not a fail safe. What will happen if the map will contain the value with `null` value? Yes. your code, in this case, will fail. – mezoni May 10 '19 at 10:55
  • Correct. As stated, I assumed the values were `Comparable`, which `null` is not. If they are not `Comparable`, you will have to figure out how you want to compare them. – lrn Aug 20 '20 at 06:00
13

To sort a map by its value in ascending order in Dart :

Map<String, int> map = {'one': 10, 'two': 5, 'three': 7, 'four': 0};

var mapEntries = map.entries.toList()
  ..sort((a, b) => a.value.compareTo(b.value));

map
  ..clear()
  ..addEntries(mapEntries);

print(map); // Must print: {four: 0, two: 5, three: 7, one: 10}
Adrien Arcuri
  • 1,962
  • 1
  • 16
  • 30
1

I suppose that you could use SortedMap from this package:

Unlike SplayTreeMap the objects can be ordered on both key and value or a combination of both.

nyarian
  • 4,085
  • 1
  • 19
  • 51
  • it gives an error. The argument type '(Pair, Pair) → int' can't be assigned to the parameter type 'Ordering' – awpathum May 10 '19 at 21:11
0

The official recomendaton is to use 'for' elements when building maps from iterables:

var temp = {'201': 4, '2017CS197': 2, '2017CS300': 6, '202': 4, '205': 3, '206': 3, '207': 5};  

final sortedInReverse = temp.entries.toList()..sort((a, b)=> b.value.compareTo(a.value));
temp = {for (var entry in sortedInReverse) entry.key: entry.value};
oblomov
  • 426
  • 6
  • 9