假设我有一个这样的数组:
var a = [94, "Neptunium", 2, "Helium", null, "Hypotheticalium", 64, "Promethium"];
偶数数组索引与以下奇数索引相关联。换句话说,94与" Neputunium"和2#" Helium"我如何根据偶数索引对数组进行排序,但在其后保留以下奇数索引值?所以我最终得到了一个像这样的数组:
a = [null, "Hypotheticalium", 2, "Helium", 64, "Promethium", 94, "Neptunium"];
注意:是的,我知道知道使用对象或ES6 Map(或者甚至,在这种情况下,使用数字作为索引的稀疏数组,如果省略null)会更合适,但我只是在探索这个来试验这门语言。谢谢你的帮助。
答案 0 :(得分:5)
var grouped = [];
for (var i = 0; i < a.length; i += 2) {
grouped.push([a[i], a[i+1]]);
}
grouped.sort(function (a, b) { return a[0] - b[0]; });
理想情况下,我建议您使用此处的grouped
结构,因为将分组的项目组合在一起似乎更有意义,而不是依赖于隐式相邻索引。但如果你需要再打开包装:
var b = [];
for (var i = 0; i < grouped.length; i++) {
b.push.apply(b, grouped[i]);
}
答案 1 :(得分:3)
由于sort
的调用顺序不一定是下一个JavaScript引擎(甚至是同一引擎的转速之间),因此您无法使用sort
直接在该数组上执行您所描述的操作。
您可以使用map
,filter
,sort
,然后使用reduce
:
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);
map
让我们生成一个包含配对条目(和null
s)对象的数组。
filter
让我们删除null
。
sort
让我们排序。
reduce
让我们生成一个结果数组(因为我们不能直接使用map
将一个条目映射到两个)。
如果你的偶数条目可能有负值,sort
回调必须以不同的方式处理事情,因为它会将null
排在那些负指数之上(当然除非你想要的)
在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);
答案 2 :(得分:1)
您需要对数组进行一些分组和适当的排序和重组。
var array = [94, "Neptunium", 2, "Helium", null, "Hypotheticalium", 64, "Promethium"],
sorted = array.reduce(function (r, a, i) {
i % 2 ? r[r.length - 1].push(a) : r.push([a]);
return r;
}, []).sort(function (a, b) {
return a[0] - b[0];
}).reduce(function (r, a) {
return r.concat(a);
});
document.write('<pre>' + JSON.stringify(sorted, 0, 4) + '</pre>');
答案 3 :(得分:0)
我喜欢我给出的特定于JS的答案背后的想法,但这是我自己的解决方案,它不依赖于原生的sort
功能,而是基于关于gnome sort的实施:
var a = [94, "Neptunium", 2, "Helium", null, "Hypotheticalium", 64, "Promethium"];
for (var i = 0, temp; i < a.length; i += 2) {
if (a[i] > a[i + 2]) {
temp = a[i];
a[i] = a[i + 2];
a[i + 2] = temp;
temp = a[i + 1];
a[i + 1] = a[i + 3];
a[i + 3] = temp;
i = i - 4;
}
}
alert(JSON.stringify(a));
当然,它不是最快的排序算法,而只是一个概念验证,表明它可以在不改变我的结构缺乏和没有大量(可能是昂贵的)函数调用的情况下完成(虽然我确实认为函数式编程更像是一个JS习语。我可以将交换代码放入自己的函数中,为了DRY,有两个调用,如下所示:
var a = [94, "Neptunium", 2, "Helium", null, "Hypotheticalium", 64, "Promethium"];
function arraySwapper(array, index1, index2) {
var temp = array[index1];
array[index1] = array[index2], array[index2] = temp;
}
for (var i = 0, j; i < a.length; i += 2) {
if (a[i] > a[i + 2]) {
for (j = i; j < i + 2; j++) { arraySwapper(a, j, j + 2); }
i -= 4;
}
}
alert(JSON.stringify(a));
&#13;