0

I have an object:

[name: string]: Person;

I would like to sort it by key, which is Person's name. Is it possible to do so or this kind of map is unsortable or I should replace it with collection of different type, which I would like to avoid.

Yoda
  • 17,363
  • 67
  • 204
  • 344
  • When you say "map", do you mean [`Map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map)? – Patrick Roberts Sep 25 '17 at 07:27
  • 2
    Possible duplicate of [Is it possible to sort a ES6 map object?](https://stackoverflow.com/questions/31158902/is-it-possible-to-sort-a-es6-map-object) – Atty Sep 25 '17 at 07:30
  • @PatrickRoberts No i don't, I mean whatever is in the code in my question because some people at my work don't use proper collections and types but stuff like you see above instead. – Yoda Sep 25 '17 at 07:31
  • even if you have a sorted map, how do you use it with that information? – Nina Scholz Sep 25 '17 at 07:33
  • @NinaScholz I imagine affecting the iteration order of a `for..in` loop would be helpful in executing linear searches with an expected outcome. – Patrick Roberts Sep 25 '17 at 07:34
  • @NinaScholz This map is part of redux state which part will be iterated to generate controls in the form in the specified order. I need it sorted. – Yoda Sep 25 '17 at 07:34
  • Same as in JavaScript: you can't. You can however get the keys using `Object.keys(obj)` and sort it and use the properties. – Saravana Sep 25 '17 at 07:35

1 Answers1

2

An object is technically sortable, though doing so tends to raise the question of why you are using one in the first place.

However, to address your concern with as little hassle as possible, here's one way to affect the insertion order of an object's keys:

function sortMap(map, compare) {
  return Object
    .entries(map)
    .sort(compare)
    .reduce((map, [key, value]) => Object.assign(map, {
      [key]: value
    }), {})
}

console.log(sortMap({
  "Joe": {},
  "Bob": {},
  "Alice": {},
  "Kevin": {},
  "Sarah": {}
}, ([a], [b]) => a.localeCompare(b)))

References:

As is stated in the linked answer, relying on the insertion order of an object does not guarantee the iteration order, since it is not in the specification, but it is currently a de-facto standard in many implementations, and it does not appear that this behavior will change in the future.

For a formal guarantee of iteration order by the specification, use a Map, as recommended in comments.

As an addendum, here's how to sort a map's iteration order, if you should choose to use them instead:

function sortMap(map, compare) {
  return new Map(
    Array
      .from(map)
      .sort(compare)
  )
}

let people = new Map([
  ['Joe', {}],
  ['Bob', {}],
  ['Alice', {}],
  ['Kevin', {}],
  ['Sarah', {}]
])

let sorted = sortMap(
  people,
  ([a], [b]) => a.localeCompare(b)
)

console.log(Array.from(sorted))
Patrick Roberts
  • 49,224
  • 10
  • 102
  • 153