Sort an array of objects based on another array of ids

You can provide a custom comparison function to JavaScript’s Array#sort method.

Use the custom comparison function to ensure the sort order:

var sortOrder = [2,3,1,4],
    items     = [{id: 1}, {id: 2}, {id: 3}, {id: 4}];

items.sort(function (a, b) {
  return sortOrder.indexOf(a.id) - sortOrder.indexOf(b.id);
});

MDN:

  • If compareFunction(a, b) returns less than 0, sort a to an index lower than b (i.e. a comes first).
  • If compareFunction(a, b) returns 0, leave a and b unchanged with respect to each other, but sorted with respect to all different elements. Note: the ECMAscript standard does not guarantee this behavior, thus, not all browsers (e.g. Mozilla versions dating back to at least 2003) respect this.
  • If compareFunction(a, b) returns greater than 0, sort b to an index lower than a (i.e. b comes first).

Hitmands made a very fair comment on the above solution:

This approach is O(n2), and would cause performance issues in big sized lists. Better to build the dictionary first, so that it stays O(n)

The above solution might be slow for large inputs because it uses indexOf for every single comparison, and indexOf is already itself slow (O(n)) compared to dictionary lookups (O(1)).

To implement Hitmands’ suggestion:

let sortOrder = [2,3,1,4],
    items     = [{id: 1}, {id: 2}, {id: 3}, {id: 4}];

const itemPositions = {};
for (const [index, id] of sortOrder.entries()) {
  itemPositions[id] = index;
}

items.sort((a, b) => itemPositions[a.id] - itemPositions[b.id]);

Leave a Comment