Since the order of the calls to sort is not necessarily the same one JavaScript engine to the next (or even between revs of the same engine), you can't use sort directly on that array to do what you've described.
You can use map, filter, sort, then reduce however:
var a = [94, "Neptunium", 2, "Helium", null, "Hypotheticalium", 64, "Promethium"];
a = a
.map(function(entry, index, array) {
return (index % 2 === 1) ? null : {
value: array[index + 1],
index: entry
};
})
.filter(function(entry) {
return entry != null;
})
.sort(function(left, right) {
return left.index - right.index; // Works even when either or both
// indexes are null, PROVIDED
// no non-null index is negative,
// because `null` will coerce to 0
})
.reduce(function(acc, entry) {
acc.push(entry.index, entry.value);
return acc;
}, []);
document.body.innerHTML = JSON.stringify(a);
The map lets us produce an array with objects for the paired entries (and nulls).
The filter lets us remove the nulls.
The sort lets us sort.
The reduce lets us produce an array of the results (since we can't use map directly to map one entry to two).
If you may have negative values for your even-numbered entries, the sort callback has to handle things differently because it will sort null above those negative indexes (unless of course that's what you want).
It's a bit more concise in ES6: (live on Babel's REPL)
let a = [94, "Neptunium", 2, "Helium", null, "Hypotheticalium", 64, "Promethium"];
a = a
.map((entry, index, array) => {
return (index % 2 === 1) ? null : {
value: array[index + 1],
index: entry
};
})
.filter(entry => entry != null)
.sort((left, right) => left.index - right.index)
.reduce((acc, entry) => {
acc.push(entry.index, entry.value);
return acc;
}, []);
console.log(a);
var a = [ ['a',1 ] ['b',2] ]