1

My first array looks like this:

[
    {entityId: 1, name: 'Total sales'},
    {entityId: 2, name: 'Total customers'},
    {entityId: 3, name: 'Reach'}
]

I have a second array which stores entityIds, and I need to sort the first array using the values of the second array. So, if my second array looks like this:

[1, 3, 2]

then my first array should be sorted like this:

[
    {entityId: 1, name: 'Total sales'},
    {entityId: 3, name: 'Reach'},
    {entityId: 2, name: 'Total customers'}
]

I know I can sort an array based on object properties by using the sort method with my own callback:

array.sort(function(a, b) {
    // ... sorting logic ...
});

However I'm struggling to wrap my head around how the sorting logic will follow the sorting rules imposed by the second array, rather than just comparing two neighbouring elements.

0

3 Answers 3

7

Use Array.prototype.indexOf:

var arr = [
    {entityId: 1, name: 'Total sales'},
    {entityId: 2, name: 'Total customers'},
    {entityId: 3, name: 'Reach'}
];

var indArr = [3, 1, 2];

arr.sort(function(a, b) {
    return indArr.indexOf(a.entityId) - indArr.indexOf(b.entityId);
});

console.log(arr);

JSFIDDLE.

Sign up to request clarification or add additional context in comments.

1 Comment

Concise, but as pointed out by Grundy, very slow as it calls indexOf twice on each iteration. It's very much faster (maybe 1,000 times faster on a big array) to not call indexOf at all.
1

Yet another variant, possibly better for big array, because iterate over arrays just twice. In case indexOf - iterate twice on every calling sort callback.

first, create map from first array

var array = [
    {entityId: 1, name: 'Total sales'},
    {entityId: 2, name: 'Total customers'},
    {entityId: 3, name: 'Reach'}
];

var map = array.reduce(function(acc,el){
    acc[el.entityId] = el;
    return acc;
},{});

second, just map second array

var indexes = [1, 3, 2];

var result = indexes.map(function(index){ return map[index];});

naive test in jsperf

4 Comments

"Better" in what way?
@RobG, just two time go over by array, in case with sort - indexOf go over array twice on ever call sort callback
@Grudy—cool, just pointing out that when you say "better" you need to say why. ;-) You should include a plain reduce method without map in your jsperf example.
@RobG, you mean your version from comment? a.reduce(function(acc, obj){return (acc[b.indexOf(obj.entityId)] = obj) && acc}, [])?
-1

Simplest code would be:

var a = [
    {entityId: 1, name: 'Total sales'},
    {entityId: 2, name: 'Total customers'},
    {entityId: 3, name: 'Reach'}
];

var b = [1,3,2];
var c = b.slice(); //create copy

for (var i = 0;i< a.length;i++)
{
   var indexOf = b.indexOf(a[i].entityId);

   c[indexOf] = a[i];
}

console.log(c)

try the jsfiddle

2 Comments

true. He answered while i was preparing this.
Consider: a.reduce(function(acc, obj){return (acc[b.indexOf(obj.entityId)] = obj) && acc}, []). Doesn't use sort though.

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.