为像数据结构这样的区块链排序对象数组

时间:2019-08-05 07:24:20

标签: javascript arrays sorting blockchain

我有一个看起来如下的对象数组:

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方法的工作原理。

任何帮助都会很棒。

谢谢

6 个答案:

答案 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;
});