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.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.