There are a few possible strategies.
Use an array of indices so that you have a layer of indirection -- create an array [0, 1, 2, 3, 4, 5, ...] and sort that with a custom comparator that dereferences 3 to array[3]. The dereferencing comparator might not obey the transitive property though so you run into undefined behavior. O(n) extra memory required.
var array = [6, 3, 18, 'four', 8, 'five', 6, 'nineteen', 'eight', 'two'];
// Create an array of indices.
var indices = [];
for (var i = array.length; --i >= 0;) { indices[i] = i; }
// indices is [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
// Sort the indices, comparing by number of corresponding element iff
// corresponding elements are both numbers.
indices.sort(function (i, j) {
var a = array[i], b = array[j]; // dereference
if (a === (a | 0) && b === (b | 0)) {
return a === b ? 0 : a < b ? -1 : 1;
} else {
return i - j;
}
});
var newArray = [];
for (var i = array.length; --i >= 0;) { newArray[i] = array[indices[i]; }
array = newArray;
The other class of solutions is to extract the numbers, sort, and then replace which requires O(n) extra memory worst-case.
var array = [6, 3, 18, 'four', 8, 'five', 6, 'nineteen', 'eight', 'two'];
var integers = array.filter(function (x) { return x === (x | 0); });
integers.sort();
for (var i = 0, k = 0; k < integers.length; ++i) {
if (array[i] === (array[i] | 0)) { array[i] = integers[k++]; }
}
[3, 6, 6, 'four', 8, 'five', 18, 'nineteen', 'eight', 'two']
? – CanSpice May 31 '11 at 17:44