This was the fastest method in my benchmark:
var a=Array.from({length:10000},()=>Math.random())
var l=a.length,o=new Array(l)
for(var i=0;i<l;i++)o[i]=i;o.sort((l,r)=>a[l]<a[r]?-1:a[l]>a[r]?1:0)
It's basically the same as the method by Sly1024 except it saves the length of the array into a variable instead of checking the length at each step of the for
loop. The code became slower if I compared the value of one item subtracted from another instead of using the greater than and lesser than operators, if I created the array of indexes using Array.from
instead of a for
loop, if I used push
instead of assigning values at an index, or if I didn't initialize the array with a length.
$ cat sortindexbench.js
var a=Array.from({length:1000},()=>Math.random())
var suite=new(require('benchmark')).Suite
suite.add('fastest',function(){
var l=a.length,o=new Array(l);for(var i=0;i<l;i++)o[i]=i;o.sort((l,r)=>a[l]<a[r]?-1:a[l]>a[r]?1:0)
}).add('length_not_saved_in_variable',function(){
var o=new Array(a.length);for(var i=0;i<a.length;i++)o[i]=i;o.sort((l,r)=>a[l]<a[r]?-1:a[l]>a[r]?1:0)
}).add('subtract_in_comparison_function',function(){
var l=a.length;var o=new Array(l);for(var i=0;i<l;i++)o[i]=i;o.sort((l,r)=>a[l]-a[r])
}).add('populate_array_of_indexes_with_array_from',function(){
var r=Array.from(Array(a.length).keys()).sort((l,r)=>a[l]<a[r]?-1:a[l]>a[r]?1:0)
}).add('array_not_initialized_with_length',function(){
var l=a.length;var o=[];for(var i=0;i<l;i++)o[i]=i;o.sort((l,r)=>a[l]<a[r]?-1:a[l]>a[r]?1:0)
}).add('push_instead_of_assign_at_index',function(){
var l=a.length;var o=new Array(l);for(var i=0;i<l;i++)o.push(i);o.sort((l,r)=>a[l]<a[r]?-1:a[l]>a[r]?1:0)
}).add('clerbois_and_Dexygen',function(){
var o=a.map((v,i)=>{return{i,v}}).sort((l,r)=>l.v<r.v?-1:l.v>r.v?1:0).map((x)=>x.i)
}).add('clerbois_and_Dexygen_array_of_arrays_instead_of_object',function(){
var o=a.map((v,i)=>[i,v]).sort((l,r)=>l[1]<r[1]?-1:l[1]>r[1]?1:0).map((x)=>x[0])
}).add('yakin_rojinegro',function(){
var m=new Map();a.forEach((v,i)=>m.set(i,v));var o=Array.from(m.entries()).sort((l,r)=>l[1]<r[1]?-1:l[1]>r[1]?1:0).map(x=>x[0]);m.clear()
}).on('cycle',function(event){console.log(String(event.target))
}).on('complete',function(){console.log('Fastest is '+this.filter('fastest').map('name'))
}).run({'async':true})
$ npm i --save benchmark
[...]
$ node sortindexbench.js
fastest x 4,728 ops/sec ±0.15% (94 runs sampled)
length_not_saved_in_variable x 4,534 ops/sec ±3.19% (92 runs sampled)
subtract_in_comparison_function x 4,587 ops/sec ±0.30% (92 runs sampled)
populate_array_of_indexes_with_array_from x 4,205 ops/sec ±0.83% (94 runs sampled)
array_not_initialized_with_length x 4,638 ops/sec ±0.60% (96 runs sampled)
push_instead_of_assign_at_index x 4,510 ops/sec ±0.46% (95 runs sampled)
clerbois_and_Dexygen x 4,250 ops/sec ±0.86% (93 runs sampled)
clerbois_and_Dexygen_array_of_arrays_instead_of_object x 4,252 ops/sec ±0.97% (93 runs sampled)
yakin_rojinegro x 3,237 ops/sec ±0.42% (93 runs sampled)
Fastest is fastest