I have an array of objects that looks the following:
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 }
]
I am getting this array from the server and there is no guarantees on the order. I want to sort the array such that, each object is followed by the object whose prev
property is the same as the id
property of the previous object.
For example,
// 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 }
]
*/
I have tried the following compareFn()
function compareFn(a, b) {
return a.id === b.prev ? 1 : -1
}
However this results in:
[
{ '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 }
]
I am quite certain that this is because of the equality in the sorting function instead of the usual >/</<=/>=
but I don't know where the problem is.
I could sort using a loop but I want to better understand how the .sort
method works.
Any help would be wonderful.
Thank you
Assuming that the prev
values won't be dependably in order (since it's a blockchain, after all):
I wouldn't use the built-in sort
for this - it requires a consistent compare function, but each item's position depends on the last sorted item's position. It'd be quite convoluted to use .sort
for this. Rather, first create a lookup table (an object indexed by prev
), then iterate starting aa prev
of 0, finding the appropriate object in the lookup table, until all objects are in the new 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 } ]; 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);
Another bonus of using this method is that it has O(n)
complexity, compared to .sort
, which has O(n log n)
complexity.
Try this:
// 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);
You could store all items with their previous id as key in a map, get the nodes without parent and iterate these parents and get the children as a sorted array.
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; }
https://developer.mozilla.org/uk/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
function compareFn(a, b) {
return a.prev - b.prev;
}
or
function compareFn(a, b) {
return a.id - b.id;
}
looks like all you need to do is this :
function compareFn(a, b) {
return a.prev - b.prev
}
As I can see previous value is always less than id. So, Ideally sorting the object by its key will work correctly.
keysSorted = arr.sort(function(a, b) {
return a.key - b.key;
});
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.