在javascript中按关系排序数组

5 javascript arrays sorting algorithm object

我想对数组进行排序.

数组中的项目具有关系.

例如.list[5]应该是before list[9]但是after list[3]


样本中的预期值仅用于测试.它并不存在.


这是一个包含关系和预期索引的示例数组.

var list = [{
  id: '0001',
  before: '0002',
  expected: 0
}, {
  id: '0002',
  before: '0007',
  after: '0001',
  expected: 4
}, {
  id: '0003',
  before: '0006',
  after: '0001',
  expected: 2
}, {
  id: '0004',
  after: '0007',
  expected: 11
}, {
  id: '0005',
  before: '0003',
  after: '0001',
  expected: 1
}, {
  id: '0006',
  before: '0002',
  after: '0001',
  expected: 3
}, {
  id: '0007',
  before: '00010',
  after: '0002',
  expected: 5
}, {
  id: '0008',
  before: '00012',
  after: '0007',
  expected: 9
}, {
  id: '0009',
  before: '0011',
  after: '0001',
  expected: 7
}, {
  id: '0010',
  before: '0009',
  after: '0007',
  expected: 6
}, {
  id: '0011',
  before: '0008',
  after: '0001',
  expected: 8
}, {
  id: '0012',
  before: '0004',
  after: '0010',
  expected: 10
}];
Run Code Online (Sandbox Code Playgroud)

Bey*_*ios 3

扩展 Jan Turo\xc5\x88:这是一个示例,说明您的问题(在有向无环图中查找全序)是如何无法解决的:

\n\n
var list = [{ id:A, before:B }, // "First" in total order\n            { id:B, after:A }, // "Last" in total order\n            { id:C, after:A, before:B },\n            { id:D, after:A, before:B }];\n
Run Code Online (Sandbox Code Playgroud)\n\n

C和之间没有完全排序D:您可以称它们相等,但是如果D您有一个列表呢D0 -> D1 -> D2

\n\n

根据您的问题类型,这可以通过预处理来解决:将 2 度节点的路径减少到单个节点,并调用通过 2 度节点的并行路径相同(也可以减少到单个节点)。在这样的预处理结束时,您会留下一棵树 - 在您的情况下应该是一个列表/路径(或单个节点,因为您减少了 2 度顶点的路径)。

\n\n

请注意,“之前”和“之后”的信息是多余的:您实际上只需要其中之一。语句“A 在 B 之前”相当于“B 在 A 之后”,并且您的非循环图只需要反映“之前”或“之后”的方向。然后,您要寻找的是一条穿过包含所有节点的图形的路径(因为它们是在“之前”或“之后”定向的,您会自动按顺序获得从第一个到最后一个的路径 - 如果存在这样的路径):

\n\n
// First build the adjacency list for "X before Y"\nvar befores = { };\nfor(var i = 0; i < count; ++i)\n    befores[list[i].id] = null;\nfunction insert(before, after) {\n    if(!before || !after)\n        return;\n    befores[before] = { next:befores[before], id:after };\n}\nfor(var i = 0; i < count; ++i) {\n    var item = list[i];\n    insert(item.after, item.id); // "X after Y" -> "Y before X"\n    insert(item.id, item.before);\n}\n\n// build complete the graph as a lookup table\n// id is "before" all elements in lookup[id]\nvar lookup = { };\nfor(var i = 0; i < count; ++i) {\n    var id = list[i].id;\n    var beforeList = [id];\n    var beforeSet = { };\n    beforeSet[id] = 1;\n    // use "A before B" and "B before C" to gain "A before C"\n    for(var j = 0; j < beforeList.length; ++j) {\n        for(var item = befores[beforeList[j]]; item != null; item = item.next) {\n            if(!beforeSet[item.id]) {\n                beforeList.push(item.id);\n                beforeSet[item.id] = 1;\n            }\n        }\n    }\n    // for our comparison we don\'t care if id is in beforeSet\n    lookup[id] = beforeSet;\n    // slice beforeList to get only the elements after id here:\n    //beforeList = beforeList.slice(1, beforeList.length);\n}\n\n// Now sort using the following\n// a) if rhs is present in "before"-set of lhs then lhs < rhs\n// b) if rhs is not present then rhs < lhs\n// c) there is information missing from our graph if a) and b) for lhs analogous lead to a different conclusion!\nlist.sort(function(lhs, rhs) {\n    if(!lhs.after || !rhs.before) return -1;\n    if(!lhs.before || !rhs.after) return 1;\n    if(lhs.id === rhs.id) return 0;\n    // different ids guaranteed, doesn\'t matter if lookup[id] contains id itself\n    var result = lookup[lhs.id][rhs.id] ? -1 : 1;\n    // expect reversing lhs and rhs to get inverse result\n    var expected = lookup[rhs.id][lhs.id] ? 1 : -1;\n    if(result != expected) {\n        // alert: there is no adjacency information between lhs and rhs!\n    }\n    return result;\n});\n
Run Code Online (Sandbox Code Playgroud)\n\n

自己测试一下:

\n\n

\r\n
\r\n
var list = [{ id:A, before:B }, // "First" in total order\n            { id:B, after:A }, // "Last" in total order\n            { id:C, after:A, before:B },\n            { id:D, after:A, before:B }];\n
Run Code Online (Sandbox Code Playgroud)\r\n
// First build the adjacency list for "X before Y"\nvar befores = { };\nfor(var i = 0; i < count; ++i)\n    befores[list[i].id] = null;\nfunction insert(before, after) {\n    if(!before || !after)\n        return;\n    befores[before] = { next:befores[before], id:after };\n}\nfor(var i = 0; i < count; ++i) {\n    var item = list[i];\n    insert(item.after, item.id); // "X after Y" -> "Y before X"\n    insert(item.id, item.before);\n}\n\n// build complete the graph as a lookup table\n// id is "before" all elements in lookup[id]\nvar lookup = { };\nfor(var i = 0; i < count; ++i) {\n    var id = list[i].id;\n    var beforeList = [id];\n    var beforeSet = { };\n    beforeSet[id] = 1;\n    // use "A before B" and "B before C" to gain "A before C"\n    for(var j = 0; j < beforeList.length; ++j) {\n        for(var item = befores[beforeList[j]]; item != null; item = item.next) {\n            if(!beforeSet[item.id]) {\n                beforeList.push(item.id);\n                beforeSet[item.id] = 1;\n            }\n        }\n    }\n    // for our comparison we don\'t care if id is in beforeSet\n    lookup[id] = beforeSet;\n    // slice beforeList to get only the elements after id here:\n    //beforeList = beforeList.slice(1, beforeList.length);\n}\n\n// Now sort using the following\n// a) if rhs is present in "before"-set of lhs then lhs < rhs\n// b) if rhs is not present then rhs < lhs\n// c) there is information missing from our graph if a) and b) for lhs analogous lead to a different conclusion!\nlist.sort(function(lhs, rhs) {\n    if(!lhs.after || !rhs.before) return -1;\n    if(!lhs.before || !rhs.after) return 1;\n    if(lhs.id === rhs.id) return 0;\n    // different ids guaranteed, doesn\'t matter if lookup[id] contains id itself\n    var result = lookup[lhs.id][rhs.id] ? -1 : 1;\n    // expect reversing lhs and rhs to get inverse result\n    var expected = lookup[rhs.id][lhs.id] ? 1 : -1;\n    if(result != expected) {\n        // alert: there is no adjacency information between lhs and rhs!\n    }\n    return result;\n});\n
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n\n

对于这个问题的一般主题,考虑拓扑排序

\n