What is the best method to sort a sparse array and keep the elements on the same indexes? For example:
a[0] = 3,
a[1] = 2,
a[2] = 6,
a[7] = 4,
a[8] = 5,
I would like after the sort to have
a[0] = 2,
a[1] = 3,
a[2] = 4,
a[7] = 5,
a[8] = 6.
What is the best method to sort a sparse array and keep the elements on the same indexes? For example:
a[0] = 3,
a[1] = 2,
a[2] = 6,
a[7] = 4,
a[8] = 5,
I would like after the sort to have
a[0] = 2,
a[1] = 3,
a[2] = 4,
a[7] = 5,
a[8] = 6.
Here's one approach. It copies the defined array elements to a new array and saves their indexes. It sorts the new array and then puts the sorted results back into the indexes that were previously used.
var a = [];
a[0] = 3;
a[1] = 2;
a[2] = 6;
a[7] = 4;
a[8] = 5;
// sortFn is optional array sort callback function,
// defaults to numeric sort if not passed
function sortSparseArray(arr, sortFn) {
var tempArr = [], indexes = [];
for (var i = 0; i < arr.length; i++) {
// find all array elements that are not undefined
if (arr[i] !== undefined) {
tempArr.push(arr[i]); // save value
indexes.push(i); // save index
}
}
// sort values (numeric sort by default)
if (!sortFn) {
sortFn = function(a,b) {
return(a - b);
}
}
tempArr.sort(sortFn);
// put sorted values back into the indexes in the original array that were used
for (var i = 0; i < indexes.length; i++) {
arr[indexes[i]] = tempArr[i];
}
return(arr);
}
Working demo: http://jsfiddle.net/jfriend00/3ank4/
.sort() ?You can
filter or Object.values to obtain an array with the values of your sparse array.sort that array, from largest to smaller. Be aware it's not stable, which may be specially problematic if some values are not numeric. You can use your own sorting implementation.map and pop to obtain the desired array. Assign it to a.var b = a.filter(function(x) {
return true;
}).sort(function(x,y) {
return y - x;
});
a = a.map([].pop, b);
Or, in ECMAScript 2017,
a = a.map([].pop, Object.values(a).sort((x,y) => y-x));
b is not needed in the ES5 code, but I used it to make the code more readable.a is unmodified if assign the map return to a new variable. Nice work, Oriol. I hate that [].sort mutates by default.a.filter(() => true) or Object.values(a).filter uses HasProperty to skip non-existing properties.var arr = [1,2,3,4,5,6,7,8,9,10];
// functions sort
function sIncrease(i, ii) { // ascending
if (i > ii)
return 1;
else if (i < ii)
return -1;
else
return 0;
}
function sDecrease(i, ii) { //descending
if (i > ii)
return -1;
else if (i < ii)
return 1;
else
return 0;
}
function sRand() { // random
return Math.random() > 0.5 ? 1 : -1;
}
arr.sort(sIncrease); // return [1,2,3,4,5,6,7,8,9,10]
arr.sort(sDecrease); // return [10,9,8,7,6,5,4,3,2,1]
arr.sort(sRand); // return random array for examle [1,10,3,4,8,6,9,2,7,5]
// Update for your needs ('position' to your key).
function updateIndexes( list ) {
list.sort( ( a, b ) => a.position - b.position )
list.forEach( ( _, index, arr ) => {
arr[ index ].position = index
} )
}
var myList = [
{ position: 8 },
{ position: 5 },
{ position: 1 },
{ position: 9 }
]
updateIndexes( myList )
// Result:
var myList = [
{ position: 1 },
{ position: 2 },
{ position: 3 },
{ position: 4 }
]