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)
扩展 Jan Turo\xc5\x88:这是一个示例,说明您的问题(在有向无环图中查找全序)是如何无法解决的:
\n\nvar 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 }];\nRun Code Online (Sandbox Code Playgroud)\n\nC和之间没有完全排序D:您可以称它们相等,但是如果D您有一个列表呢D0 -> D1 -> D2?
根据您的问题类型,这可以通过预处理来解决:将 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});\nRun Code Online (Sandbox Code Playgroud)\n\n自己测试一下:
\n\nvar 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 }];\nRun 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});\nRun Code Online (Sandbox Code Playgroud)\r\n对于这个问题的一般主题,考虑拓扑排序。
\n