I have two arrays of objects and I need to match the order of one of the arrays with the other. Here's an example:
const outOfOrderArray = [{field: 'foo'}, {field: 'bar'}, {field: 'bazz'}, {field: 'bizz'}];
const arrayInProperOrder = [{field: 'bizz'}, {field: 'bazz'}, {field: 'foo'}, {field: 'bar'}];
What can I do to make the outOfOrderArray
match the order of objects in arrayInProperOrder
?
3 Answers 3
Here is how you can do it in one less loop than the solution of @Faly. There is no need to sort the array. You may just loop over arrayInProperOrder
and find matching element from outOfOrderArray
so that the latter becomes in order.
const outOfOrderArray = [{field: 'foo'}, {field: 'bar'}, {field: 'bazz'}, {field: 'bizz'}];
const arrayInProperOrder = [{field: 'bizz'}, {field: 'bazz'}, {field: 'foo'}, {field: 'bar'}];
const newArray = [];
arrayInProperOrder.forEach(item => {
const original = outOfOrderArray.find(i => i.field === item.field);
if (original) {
newArray.push(original);
}
});
console.log(newArray);
If you need it in place, just assign newArray
to outOfOrderArray
.
You can create a temp object to store the order and use it as a basis on sort()
Use Infinity
as the default value if some field is not found on temp object.
const outOfOrderArray = [{field: 'foo'}, {field: 'bar'}, {field: 'bazz'}, {field: 'bizz'}];
const arrayInProperOrder = [{field: 'bizz'}, {field: 'bazz'}, {field: 'foo'}, {field: 'bar'}];
//Make a temp object - This will store the order of the field. This nessasary so that no need to search every reiteration on sort()
const tempObj = arrayInProperOrder.reduce((c, v, i) => Object.assign(c, {[v.field]: i + 1}), {});
//Sort the array.
outOfOrderArray.sort((a, b) => (tempObj[a.field] || Infinity) - (tempObj[b.field] || Infinity));
console.log(outOfOrderArray);
You can use array.prototype.sort
and array.prototype.findIndex
:
const outOfOrderArray = [{field: 'foo'}, {field: 'bar'}, {field: 'bazz'}, {field: 'bizz'}];
const arrayInProperOrder = [{field: 'bizz'}, {field: 'bazz'}, {field: 'foo'}, {field: 'bar'}];
outOfOrderArray.sort(
(a, b) => arrayInProperOrder.findIndex(e => e.field === a.field) - arrayInProperOrder.findIndex(e => e.field === b.field)
);
console.log(outOfOrderArray);
If you care about performance, you can build an object allowing you to get the index by the field value, from arrayInProperOrder array:
const outOfOrderArray = [{field: 'foo'}, {field: 'bar'}, {field: 'bazz'}, {field: 'bizz'}];
const arrayInProperOrder = [{field: 'bizz'}, {field: 'bazz'}, {field: 'foo'}, {field: 'bar'}];
const indexes = arrayInProperOrder.reduce((m, o, i) => (m[o.field] = i, m), {});
outOfOrderArray.sort(
(a, b) => indexes[a.field] - indexes[b.field]
);
console.log(outOfOrderArray);
-
Performing a two linear searches at every step of a sort operation doesn't seem like a great idea. The
.sort()
method really isn't needed in the first place.user2437417– user24374172018年05月11日 14:11:43 +00:00Commented May 11, 2018 at 14:11 -
Performance does not always pose problem, depending on the quantity of data to be processedFaly– Faly2018年05月11日 14:15:43 +00:00Commented May 11, 2018 at 14:15
const outOfOrderArray = [{field: 'foo'}, {field: 'foo'}, {field: 'bar'}, {field: 'bazz'}, {field: 'bizz'}]
where{field: 'foo'}
is appearing 2 times,