我有一个看起来如下的对象数组:
var arr = [
{ id: 1, prev: 0 },
{ id: 4, prev: 3 },
{ id: 3, prev: 2 },
{ id: 8, prev: 7 }
{ id: 5, prev: 4 },
{ id: 7, prev: 6 },
{ id: 6, prev: 5 },
{ id: 2, prev: 1 }
]
我正在从服务器获取此阵列,并且订单上没有保证。我想对数组进行排序,以便每个对象后跟一个对象,该对象的prev
属性与上一个对象的id
属性相同。
例如,
// Given the following array
var arr = [
{ id: 1, prev: 0 },
{ id: 4, prev: 3 },
{ id: 3, prev: 2 },
{ id: 8, prev: 7 }
{ id: 5, prev: 4 },
{ id: 7, prev: 6 },
{ id: 6, prev: 5 },
{ id: 2, prev: 1 }
]
function compareFn(a, b) {
}
var sortedArray = arr.sort( compareFn );
console.log(sortedArray);
/* Should be
[
{ id: 1, prev: 0 },
{ id: 2, prev: 1 },
{ id: 3, prev: 2 },
{ id: 4, prev: 3 }
{ id: 5, prev: 4 },
{ id: 6, prev: 5 },
{ id: 7, prev: 6 },
{ id: 8, prev: 7 }
]
*/
我尝试了以下compareFn()
function compareFn(a, b) {
return a.id === b.prev ? 1 : -1
}
但这会导致:
[
{ 'id': 1, 'prev': 0 },
{ 'id': 3, 'prev': 2 },
{ 'id': 4, 'prev': 3 },
{ 'id': 8, 'prev': 7 },
{ 'id': 5, 'prev': 4 },
{ 'id': 6, 'prev': 5 },
{ 'id': 7, 'prev': 6 },
{ 'id': 2, 'prev': 1 }
]
我非常确定这是由于排序函数中的相等性而不是通常的>/</<=/>=
引起的,但是我不知道问题出在哪里。
我可以使用循环进行排序,但是我想更好地了解.sort
方法的工作原理。
任何帮助都会很棒。
谢谢
答案 0 :(得分:3)
假设prev
值的顺序不可靠(毕竟因为它是区块链):
我不会为此使用内置的sort
-它需要一个一致的比较功能,但是每个项目的位置取决于 last 排序项目的位置。为此,使用.sort
非常费时。相反,首先创建一个查找表(由prev
索引的对象),然后从0的prev
开始迭代,在查找表中找到合适的对象,直到所有对象都在新数组中: / p>
var arr = [
{ id: 1, prev: 0 },
{ id: 4, prev: 3 },
{ id: 3, prev: 2 },
{ id: 8, prev: 7 },
{ id: 5, prev: 4 },
{ id: 7, prev: 6 },
{ id: 6, prev: 5 },
{ id: 2, prev: 1 }
];
const itemsByPrev = arr.reduce((a, item) => {
a[item.prev] = item;
return a;
}, {});
const sorted = [];
let lastId = 0;
const { length } = arr;
while (sorted.length < length) {
const obj = itemsByPrev[lastId];
sorted.push(obj);
lastId = obj.id;
}
console.log(sorted);
使用此方法的另一个好处是,与具有O(n)
复杂度的.sort
相比,它具有O(n log n)
复杂度。
答案 1 :(得分:0)
尝试一下:
// Given the following array
var arr = [
{ id: 1, prev: 0 },
{ id: 4, prev: 3 },
{ id: 3, prev: 2 },
{ id: 8, prev: 7 },
{ id: 5, prev: 4 },
{ id: 7, prev: 6 },
{ id: 6, prev: 5 },
{ id: 2, prev: 1 }
]
arr.sort(function(a, b) {
return a.id - b.id;
});
console.log(arr);
答案 2 :(得分:0)
您可以将所有具有先前ID的项作为键存储在地图中,获取没有父项的节点并迭代这些父项,然后将子项作为已排序的数组。
var array = [{ id: 1, prev: 0 }, { id: 4, prev: 3 }, { id: 3, prev: 2 }, { id: 8, prev: 7 }, { id: 5, prev: 4 }, { id: 7, prev: 6 }, { id: 6, prev: 5 }, { id: 2, prev: 1 }],
map = array.reduce((m, o) => m.set(o.prev, o), new Map),
first = array.reduce((s, { id }) => (s.delete(id), s), new Set([...map.keys()])),
result = [];
first.forEach(id => {
var temp;
while (map.has(id)) {
result.push(temp = map.get(id));
id = temp.id;
}
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
答案 3 :(得分:-1)
https://developer.mozilla.org/uk/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
function compareFn(a, b) {
return a.prev - b.prev;
}
或
function compareFn(a, b) {
return a.id - b.id;
}
答案 4 :(得分:-1)
看起来您需要做的就是这个:
function compareFn(a, b) {
return a.prev - b.prev
}
答案 5 :(得分:-1)
如我所见,先前的值始终小于id。因此,理想情况下按对象的键对对象进行排序可以正常工作。
keysSorted = arr.sort(function(a, b) {
return a.key - b.key;
});