skip to Main Content

I have a map with keys = day of the month, 131. If I understand correctly, Javascript converts the map keys into strings anyways.

After sorting using the standard new Map([...myMap.entries()].sort())
the map becomes sorted by the keys as:

1, 11, 12, 13, ..., 19, 2, 20, 21, 22, 23, ... 29, 3, 30, 31.

I found a way to sort as 1,2,3,4,5, ... by converting the decimal keys to strings and pad single numbers with 0:

mykey.toString().padStart(2, "0");

I suspect this is too artificial and there should be some pre-built in Javascript method to achieve the normal sort of a map by a decimal values of the keys.

Any suggestions how to sort Javascript map by decimal keys in a nicer way?

Tried new Map([…myMap.entries()].sort()) – the map got sorted as : 1, 11, 12, …, 19, 2, 20, 21, 22, … 29, 3, 30, 31.

2

Answers


  1. While any type can be used in the key of a Map() object, when using the default sort() implementation they are coerced to strings.

    To fix this you need to implement your own sorting logic which explicitly compares them as numeric values. In the example below it uses integers, but this can easily be updated to use parseFloat() if decimal comparison is required.

    const map = new Map();
    map.set(3, "foo");
    map.set(1, "foo");
    map.set(8, "foo");
    map.set(10, "foo");
    map.set(5, "foo");
    map.set(2, "foo");
    map.set(4, "foo");
    map.set(7, "foo");
    map.set(6, "foo");
    map.set(9, "foo");
    
    // does not work:
    const mapFailedSort =  new Map([...map.entries()].sort());
    console.log(mapFailedSort);
    
    // works (improved thanks to @InSync)
    const mapAsc = new Map([...map.entries()].sort(([a], [b]) => a - b));
    console.log(mapAsc)

    Note: The snippet console doesn’t appear to play very nicely with Map() objects – check the output in the devtools console to see the sorting has worked correctly.

    Login or Signup to reply.
  2. You can sort keys instead of entries, this will give you better performance since you don’t create and copy array data for values. To sort the keys as numbers you should provide a custom comparator function otherwise the keys will be sorted as strings:

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

    const map = new Map();
    let count = 15;
    while(count--){
      map.set(count, `item${count}`);
    }
    
    const result = [...map.keys()].sort((a,b) => a-b).reduce((r, key) => r.set(key, map.get(key)), new Map);
    console.log(...result);

    And the benchmark with a big map (a small map looks the same):

    enter image description here

    <script benchmark data-count="1">
    
    const map = new Map();
    let count = 500000;
    while(count--){
      const id = Math.floor(Math.random()*1000000);
      map.set(id, `item${id}`);
    }
    
    // @benchmark Rory McCrossan/InSync
    new Map([...map.entries()].sort(([a], [b]) => a - b));
    
    
    // @benchmark Alexander
    [...map.keys()].sort((a,b) => a-b).reduce((r, key) => r.set(key, map.get(key)), new Map);
    
    </script>
    
    <script src="https://cdn.jsdelivr.net/gh/silentmantra/benchmark/loader.js"></script>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search