假设我有一个Javascript数组,如下所示:
var test = ['b', 'c', 'd', 'a'];
我想对数组进行排序。显然,我可以这样做来对数组进行排序:
test.sort(); //Now test is ['a', 'b', 'c', 'd']
但我真正想要的是一个索引数组,它指示排序元素相对于原始元素的位置。我不太清楚怎么说这个,所以也许这就是为什么我无法弄清楚如何去做。
如果这样的方法被称为sortIndices(),那么我想要的是:
var indices = test.sortIndices();
//At this point, I want indices to be [3, 0, 1, 2].
'a'位于第3位,'b'位于0,'c'位于1且'd'在原始数组中为2。因此,[3,0,1,2]。
一种解决方案是对数组的副本进行排序,然后遍历排序的数组并找到原始数组中每个元素的位置。但是,这感觉很笨拙。
现有方法是否符合我的要求?如果没有,您将如何编写一个执行此操作的方法?
答案 0 :(得分:40)
var test = ['b', 'c', 'd', 'a'];
var test_with_index = [];
for (var i in test) {
test_with_index.push([test[i], i]);
}
test_with_index.sort(function(left, right) {
return left[0] < right[0] ? -1 : 1;
});
var indexes = [];
test = [];
for (var j in test_with_index) {
test.push(test_with_index[j][0]);
indexes.push(test_with_index[j][1]);
}
修改强>
你们对for .. in
是正确的。如果有人打开阵列原型,那将会破坏,我经常烦恼地观察。这是固定的,并且包含在一个更有用的功能中。
function sortWithIndeces(toSort) {
for (var i = 0; i < toSort.length; i++) {
toSort[i] = [toSort[i], i];
}
toSort.sort(function(left, right) {
return left[0] < right[0] ? -1 : 1;
});
toSort.sortIndices = [];
for (var j = 0; j < toSort.length; j++) {
toSort.sortIndices.push(toSort[j][1]);
toSort[j] = toSort[j][0];
}
return toSort;
}
var test = ['b', 'c', 'd', 'a'];
sortWithIndeces(test);
alert(test.sortIndices.join(","));
答案 1 :(得分:21)
我只需用数字0..n-1填充一个数组,然后使用比较函数对其进行排序。
var test = ['b', 'c', 'd', 'a'];
var len = test.length;
var indices = new Array(len);
for (var i = 0; i < len; ++i) indices[i] = i;
indices.sort(function (a, b) { return test[a] < test[b] ? -1 : test[a] > test[b] ? 1 : 0; });
console.log(indices);
答案 2 :(得分:6)
Dave Aaron Smith是正确的,不过我觉得在这里使用Array map()很有意思。
var test = ['b', 'c', 'd', 'a'];
// make list with indices and values
indexedTest = test.map(function(e,i){return {ind: i, val: e}});
// sort index/value couples, based on values
indexedTest.sort(function(x, y){return x.val > y.val ? 1 : x.val == y.val ? 0 : -1});
// make list keeping only indices
indices = indexedTest.map(function(e){return e.ind});
答案 3 :(得分:2)
Array.prototype.sortIndices = function (func) {
var i = j = this.length,
that = this;
while (i--) {
this[i] = { k: i, v: this[i] };
}
this.sort(function (a, b) {
return func ? func.call(that, a.v, b.v) :
a.v < b.v ? -1 : a.v > b.v ? 1 : 0;
});
while (j--) {
this[j] = this[j].k;
}
}
YMMV关于如何向Array原型添加函数和内联变异数组的感觉,但这允许对可以比较的任何对象的数组进行排序。它需要一个可用于排序的可选功能,就像Array.prototype.sort
。
一个例子,
var test = [{b:2},{b:3},{b:4},{b:1}];
test.sortIndices(function(a,b) { return a.b - b.b; });
console.log(test); // returns [3,0,1,2]
答案 4 :(得分:2)
您可以使用es6(生成0->N-1
索引数组并根据输入值对其进行排序)使用单行完成此操作。
var test = ['b', 'c', 'd', 'a']
var result = Array.from(Array(test.length).keys())
.sort((a, b) => test[a] < test[b] ? -1 : (test[b] < test[a]) | 0)
答案 5 :(得分:1)
这是clerbois回答的一个更惯用的ES6版本,请参见他/她的评论:
return test.map((val, ind) => {return {ind, val}})
.sort((a, b) => {return a.val > b.val ? 1 : a.val == b.val ? 0 : -1 })
.map((obj) => obj.ind);
答案 6 :(得分:0)
您可以使用Map对象执行此操作。只需将键/值设置为索引/值,然后使用Array.from将Iterator设为二维数组,然后对索引,值或两者进行排序。
function sorting(elements) {
const myMap = new Map();
elements.forEach((value, index) => {
myMap.set(index, value);
});
const arrayWithOrderedIndexes = Array.from(myMap.entries()).sort((left, right) => {return left[1] < right[1] ? -1 : 1});
myMap.clear();
return arrayWithOrderedIndexes.map(elem => elem[0]);
}
const elements = ['value','some value','a value','zikas value','another value','something value','xtra value'];
sorting(elements);
答案 7 :(得分:-1)
您可以做到这一点!
detailItems.slice()
.map((r, ix) => {
r._ix = ix;
return r;
})
.sort((a,b) => {
... /* you have a._ix or b._ix here !! */
})
.slice()
克隆您的数组以防止产生副作用:))