96

How to sort this map by value?

var map = new Map();
map.set('orange', 10);
map.set('apple', 5);
map.set('banana', 20);
map.set('cherry', 13);
5
  • 5
    Map is a data structure, which is not supposed to be able to be sorted. It stores key-value pairs, and there is not much sense in sorting a hashtable. You can convert it to an array, and sort this array, if you want. Commented Jun 23, 2016 at 4:42
  • I agree you should not depend on the sort of a Map Commented Jun 23, 2016 at 4:43
  • Possible duplicate of Sort a dictionary by value in JavaScript Commented Jun 23, 2016 at 4:45
  • use plain Objects instead of Maps to store sorted alphabetically-keyed key:value pairs. Commented Jun 23, 2016 at 5:37
  • The Map object holds key-value pairs and remembers the original insertion order of the keys. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… Commented Jul 13, 2022 at 7:06

9 Answers 9

183
const myMap = new Map();
myMap.set("a",3);
myMap.set("c",4);
myMap.set("b",1);
myMap.set("d",2);

// sort by value
const mapSort1 = new Map([...myMap.entries()].sort((a, b) => b[1] - a[1]));
console.log(mapSort1);
// Map(4) {"c" => 4, "a" => 3, "d" => 2, "b" => 1}

const mapSort2 = new Map([...myMap.entries()].sort((a, b) => a[1] - b[1]));
console.log(mapSort2);
// Map(4) {"b" => 1, "d" => 2, "a" => 3, "c" => 4}

// sort by key
const mapSort3 = new Map([...myMap.entries()].sort());
console.log(mapSort3);
// Map(4) {"a" => 3, "b" => 1, "c" => 4, "d" => 2}

const mapSort4 = new Map([...myMap.entries()].reverse());
console.log(mapSort4);
// Map(4) {"d" => 2, "b" => 1, "c" => 4, "a" => 3}
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks! You method is very clean. However could you please explain the new Map([...myMap.entries()]). Is this method compatible with Internet Explorer?
Yes this is what I thought. Any idea of a clean method that would work with IE?
53

Yo could take a different approach and change Symbol.iterator of Map.prototype[@@iterator]() for a custom sorted result.

var map = new Map();

map.set("orange", 10);
map.set("apple", 5);
map.set("banana", 20);
map.set("cherry", 13);

map[Symbol.iterator] = function* () {
    yield* [...this.entries()].sort((a, b) => a[1] - b[1]);
}

for (let [key, value] of map) {     // get data sorted
    console.log(key + ' ' + value);
}

console.log([...map]);              // sorted order
console.log([...map.entries()]);    // original insertation order
.as-console-wrapper { max-height: 100% !important; top: 0; }

2 Comments

I think this is cool but should be used very carefully so you're not sorting already sorted lists.
In fact I think it would be good to add an "isSorted" property, and if so then don't sort. One could go further and add a [Symbol.set] generator for binary insertion, and [Symbol.get] for binary search which forked based on the isSorted flag. I'm concerned though about the long term safety of this approach. I think indirection would likely be more prudent.
10

You can shorten the function and use this in ES6- using arrow function (lambda)

 let m2= new Map([...m.entries()].sort((a,b) => b[1] - a[1]))

Comments

6

In ES6 you can do it like this: (assume your Map object is m).

[...m].map(e =>{ return e[1];}).slice().sort(function(a, b) {
  return a - b; 
});

the spread operator turns a Map object into an array, then takes out the second element of each subarray to build a new array, then sort it. If you want to sort in descending order just replace a - b with b - a.

Comments

5

You can use list maps instead of map only. Try this:

var yourListMaps = [];
var a = {quantity: 10, otherAttr: 'tmp1'};
var b = {quantity: 20, otherAttr: 'tmp2'};
var c = {quantity: 30, otherAttr: 'tmp3'};
yourListMaps.push(a);
yourListMaps.push(b);
yourListMaps.push(c);

And if you want to sort by quantity, you can:

// Sort c > b > a
yourListMaps.sort(function(a,b){
    return b.quantity - a.quantity;
});

or

// Sort a > b > c
yourListMaps.sort(function(a,b){
    return a.quantity - b.quantity;
});

2 Comments

this didnt work. i get result in insertion order only
try again now? I think you copy or write something wrong ?
3

To sort a map object use the below code.

const map = new Map();
map.set("key","value");
map.set("key","value");

const object = Object.keys(map.sort().reduce((a,b) => (a[k] = map[a], b), {});

console.log(object);

//This will work to sort a map by key.

Comments

1

There are several valid answers here but I think the "ordered map" aspect complicates and confuses things unnecessarily.

Assuming it is sufficient to get a list of the keys in the map sorted by value, rather than a map whose entries are sorted by value, then something like this works:

var map = {
  orange: 10,
  apple: 5,
  banana: 20,
  cherry: 13
}

var sorted_keys = Object.keys(map).sort(function(a,b) { return map[a] - map[b]; });

which yields:

["apple", "orange", "cherry", "banana"]

This is a little less elegant if you actually want to iterate over the map entries (now you need to iterate over the array of sorted keys and fetch the values instead) but:

  1. This logic is much easier for my simple mind to follow and to remember.

  2. There's a pretty common use case for "sort this map by value" in which you actually want the sorted list of keys: using a map to keep a tally. (E.g., iterating over the words in a file using a map to keep try of how often each word appears then sorting that map to get a list of words by frequency.)

For the general case in which the values in the map aren't necessarily numeric, replace the comparator function (the function passed to Object.keys(map).sort) with something like:

function(a, b) {
  return (a < b) ? -1 : ( (a > b) ? 1 : 0 );
}

(which is essentially:

function(a, b) {
  if (a < b) {
    return -1;
  } else if (a > b) {
    return 1;
  } else {
    return 0;
  }
}

but using the ternary (? :) operator.)

But bear in mind that the behavior of JavaScript's < and > operators is sometimes a little counter-intuitive with mixed types so depending on the values in your map you may want to include explicit type-casting logic in your comparator.

Comments

1

I also wanted to sort a Map by value but my key is a number and value is a string. (Map<number, string>), and wanted to do it using TypeScript.

This is what worked for me, using localeCompare

let json = [
    {
        "key": 2952,
        "value": "Sample Text"
    },
    {
        "key": 2961,
        "value": "Sample Text 1"
    },
    {
        "key": 2962,
        "value": "1Sample Text"
    },
    {
        "key": 2987,
        "value": "3Sample Text"
    },
    {
        "key": 2988,
        "value": "#Sample Text"
    },
    {
        "key": 4585,
        "value": "Ö Sample Text"
    },
    {
        "key": 4594,
        "value": "@Sample Text"
    }
]

let myMap = new Map(Object.entries(json));

myMap = new Map([...myMap.entries()].sort((a, b) => a[1].value.localeCompare(b[1].value)));

myMap.forEach((x) => {
    console.log(x.value)
})

Comments

-2

To Sort Object simply use

const sortedObject = mapObject.sort((a,b)=>return b.value - a.value) 

1 Comment

sort() is not a function on the Map type.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.