0

I can imagine this has been asked a few times but I literally cannot find an example of a solution to the specific problem I'm trying to figure out.

So I have an object, like so:

var collection = [{ id: 0 }, { id: 1 }, { id: 2 }]; 

I then have an array, which is the 'order', like so:

var order = [2, 0, 1]; 

I want to use the 'order' array to reorder the collection in that specific order. I've been trying quite a few solutions with the .sort function, but I can't find one that fits. Can anyone enlighten me? Probably simple, I'm hoping.

2
  • Not sure what your needs are but in such a simple case you could order by index. Commented Feb 10, 2013 at 23:42
  • Be wary of solutions that use multiple, uncached calls to indexOf, since they will involve sweeping through order many, many times. Commented Feb 10, 2013 at 23:46

5 Answers 5

5

You can use the sort() method to accomplish this using indexOf:

collection.sort(function(a, b){ return order.indexOf(a.id) > order.indexOf(b.id); }); 
Sign up to request clarification or add additional context in comments.

Comments

2

You can use indexOf function on the order array in the custom sort function, like this:

collection.sort(function(x, y) { return order.indexOf(x.id) > order.indexOf(y.id); }); 

2 Comments

Seems like I need to type faster, @ozk is faster than me :(.
StackOverflow is all about typing agility :)
1

seems to be as easy as that:

var collection = [{ id: 0 }, { id: 1 }, { id: 2 }]; var order = [2, 0, 1]; var sorted = []; for(var i=0,c=order.length;i<c;i++){ sorted.push(collection[order[i]]); } 

1 Comment

I don't think that does what the OP is asking for. That takes collection and uses order to say "list the third, then the first, then the second from collection". I think that OP wants "list id:2, then id:0, then id:1"
1

Try that:

var collection = [{ id: 0 }, { id: 1 }, { id: 2 }]; var order = [2, 0, 1]; var sortedCollection = []; for ( var i = 0; i < order.length; i++ ) sortedCollection.push(collection[order[i]]); console.log(sortedCollection); 

Comments

0

The thing you want to avoid here is scanning through either of these arrays more than you have to.

Here's one solution that avoids this:

/* * Map the indexes of the objects in collection to their final location */ var sortIndex = {}; order.forEach(function(value, index) { sortIndex[value] = index; }); /* * Put the objects in collection into their new, sorted collection */ var sortedCollection = []; collection.forEach(function(value) { var sortedLocation = sortIndex[value.id]; sortedCollection[sortedLocation] = value; }); 

Thus, we have a single scan through each of the arrays, keeping the work down to a minimum.

I've used forEach here as a convenience; you could use a library like Lodash or Underscore, or rewrite this to use explicit iteration over the arrays.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.