1

I have this two arrays

var refArray = ['India','Pakistan','Nepal','Bhutan','SreeLanka','Singapore','Thailand','China','Russia']
var beenThere = ['Russia','Bhutan','India']

I need to sort beenThere on the order of refArray for display purpose, so if I sort beenThere, result should be,

['India','Bhutan','Russia']

Where can I get one algorithm.

0

4 Answers 4

3

a faster way is to use the pre-sorted array as a template, and limit the indexOf() work to a single indexOf() call on the sub-set items, instead of 2-indexOf() calls on all items.

var refArray = ['India','Pakistan','Nepal','Bhutan','SreeLanka','Singapore','Thailand','China','Russia']
var beenThere = ['Russia','Bhutan','India'];
function contains(a){return this.indexOf(a)!==-1; }
refArray.filter(contains, beenThere); // == ["India", "Bhutan", "Russia"]
Sign up to request clarification or add additional context in comments.

4 Comments

"a faster way is"—than what? I think you need to back that up. ;-)
indexOf() is expensive. if you run indexOf() on the big array twice per iteration, it does more work and thus takes more time than running one indexOf() on the smaller array each iteration. this will be especially true where indexOf() is polyfilled by user-land code.
Well, testing in various browsers shows filter is slightly faster in Safari, but slower in Firefox and Chrome. Tests with different size arrays may change that. Regardless of theory, it's the implementation that matters. ;-)
@RobG And it actually makes sense, because filter has to check all the refArray items, while with sort+indexOf we need to visit only few items in beenArray.
2

Try to use indexOf:

beenThere.sort(function(a, b) {
    return refArray.indexOf(a) - refArray.indexOf(b); 
}); // ['India','Bhutan','Russia']

Comments

2

Just compare the indices of each element in the refArray using indexOf method.

beenThere.sort(function(a,b){
return refArray.indexOf(a)-refArray.indexOf(b);
})

Comments

1

since the data are strings, and the strings don't have commas, you can avoid all user-land iteration with a dynamic RegExp:

var refArray = ['India','Pakistan','Nepal','Bhutan','SreeLanka','Singapore','Thailand','China','Russia']
var beenThere = ['Russia','Bhutan','India'];


(","+refArray+",").match(RegExp(",("+beenThere.join("|")+"),","g")).join(",").split(/,+/).slice(1,-1); 
// ==  ["India", "Bhutan", "Russia"]

that one is nice in that it doesn't need [].indexOf(), so it works in older browsers. you can use another delimeter besides comma if the data has commas, with some slightly uglier code...

or, using filter for the iteration, but with a native method instead of a user-land function:

var refArray = ['India','Pakistan','Nepal','Bhutan','SreeLanka','Singapore','Thailand','China','Russia']
var beenThere = ['Russia','Bhutan','India'];

refArray.filter(/./.test, RegExp("("+beenThere.join("|")+")","g"));
// == ["India", "Bhutan", "Russia"]

these would probably perform faster than indexOf(), but sorting is a weird operation, with lots of opportunity for behind-the-scenes optimization, so results may vary.

Comments

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.