我正在尝试对有时彼此无法比拟的值进行排序。我正在排序的数据类似于树
1. if a depends on b, then a should be sorted after b
2. if b depends on a, then b should be sorted after a
3. if neither a or b depend on each other then they are incomparable and no comparison can be drawn
我目前在javascript中使用自定义比较功能的sort函数。但我怀疑它不合适,因为我基本上需要Topological Sorting
带测试的示例代码:
// k depends on nothing - but every other element depends on k, so k should come first
var k = {
uuid: 'k',
dependsOn: []
};
// z depends on k and so k must come before z
var z = {
uuid: 'z',
dependsOn: ['k']
}
// y should be go before x as x depends on y
// y also depends on k so k should go before y
var y = {
uuid: 'y',
dependsOn: ['k']
}
// x has both y and k as its dependencies
var x = {
uuid: 'x',
dependsOn: ['y', 'k']
}
function compare(a, b) {
// if they have the same uuid; then they are the same
if (a.uuid === b.uuid) {
return 0
}
// if a depends on b, then a should be after b
for (var i = 0, len = a.dependsOn.length; i < len; i++) {
var dependsOn = a.dependsOn[i];
if (dependsOn === b.uuid) {
return 1
}
}
// if b depends on a, then b should be after a
for (var i = 0, len = b.dependsOn.length; i < len; i++) {
var dependsOn = b.dependsOn[i];
if (dependsOn === a.uuid) {
return -1
}
}
// this is the edge case,
// if neither a or b depends on each other, then they don't have relative ranking
return null
}
// this is every possible permutation - they should all sort to the same orders
// expected order k, z, y, x or k, y, z, x or k, y, x, z
// because:
// k -> z as z depends on k
// k -> y as y depends on k
// no relative ranking between z and y as they don't depend on each other
// x depends on both y and k so x will come after them
var perms = [
[x, y, z, k],
[x, y, k, z],
[x, z, y, k],
[x, z, k, y],
[x, k, y, z],
[x, k, z, y],
[y, x, z, k],
[y, x, k, z],
[y, z, x, k],
[y, z, k, x],
[y, k, x, z],
[y, k, z, x],
[z, x, y, k],
[z, x, k, y],
[z, y, x, k],
[z, y, k, x],
[z, k, x, y],
[z, k, y, x],
[k, x, y, z],
[k, x, z, y],
[k, y, x, z],
[k, y, z, x],
[k, z, x, y],
[k, z, y, x],
]
var _ = require('underscore')
perms.forEach(function(perm) {
var s = perm.sort(compare)
var p = _.pluck(s, 'uuid')
console.log(p, _.isEqual(p, ['k', 'z', 'y', 'x']) || _.isEqual(p, ['k', 'y', 'z', 'x']) || _.isEqual(p, ['k', 'y', 'x', 'z']))
})
示例输出(带注释):
[ 'k', 'y', 'x', 'z' ] true
[ 'k', 'y', 'x', 'z' ] true
[ 'k', 'x', 'z', 'y' ] false \\ x depends on k and y so it should be after y
[ 'k', 'x', 'z', 'y' ] false
[ 'k', 'y', 'x', 'z' ] true
[ 'k', 'x', 'z', 'y' ] false \\ x depends on k and y so it should be after y
[ 'k', 'y', 'x', 'z' ] true
[ 'k', 'y', 'x', 'z' ] true
[ 'k', 'y', 'z', 'x' ] true
[ 'k', 'y', 'z', 'x' ] true
[ 'k', 'y', 'x', 'z' ] true
[ 'k', 'y', 'z', 'x' ] true
[ 'k', 'z', 'y', 'x' ] true
[ 'k', 'z', 'y', 'x' ] true
[ 'k', 'z', 'y', 'x' ] true
[ 'k', 'z', 'y', 'x' ] true
[ 'k', 'z', 'y', 'x' ] true
[ 'k', 'z', 'y', 'x' ] true
[ 'k', 'y', 'x', 'z' ] true
[ 'k', 'x', 'z', 'y' ] false \\ x depends on k and y so it should be after y
[ 'k', 'y', 'x', 'z' ] true
[ 'k', 'y', 'z', 'x' ] true
[ 'k', 'z', 'y', 'x' ] true
[ 'k', 'z', 'y', 'x' ] true
答案 0 :(得分:0)
我找到了一个看似不是非常积极维护的图书馆来完成这项工作:
// k depends on nothing - but every other element depends on k, so k should come first
var k = {
uuid: 'k',
dependsOn: []
};
// z depends on k and so k must come before z
var z = {
uuid: 'z',
dependsOn: ['k']
}
// y should be go before x as x depends on y
// y also depends on k so k should go before y
var y = {
uuid: 'y',
dependsOn: ['k']
}
// x has both y and k as its dependencies
var x = {
uuid: 'x',
dependsOn: ['y', 'k']
};
function Edges(array) {
var edges = []
for (var k in array) {
var node = array[k]
node.dependsOn.forEach(function(dependency) {
edges.push([dependency].concat(node.uuid))
})
}
return edges
}
// this is every possible permutation - they should all sort to the same orders
// expected order k, z, y, x or k, y, z, x or k, y, x, z
// because:
// k -> z as z depends on k
// k -> y as y depends on k
// no relative ranking between z and y as they don't depend on each other
// x depends on both y and k so x will come after them
var perms = [
[x, y, z, k],
[x, y, k, z],
[x, z, y, k],
[x, z, k, y],
[x, k, y, z],
[x, k, z, y],
[y, x, z, k],
[y, x, k, z],
[y, z, x, k],
[y, z, k, x],
[y, k, x, z],
[y, k, z, x],
[z, x, y, k],
[z, x, k, y],
[z, y, x, k],
[z, y, k, x],
[z, k, x, y],
[z, k, y, x],
[k, x, y, z],
[k, x, z, y],
[k, y, x, z],
[k, y, z, x],
[k, z, x, y],
[k, z, y, x],
]
var _ = require('underscore')
var toposort = require('toposort')
perms.forEach(function(perm) {
var p = toposort(Edges(perm));
console.log(p, _.isEqual(p, ['k', 'z', 'y', 'x']) || _.isEqual(p, ['k', 'y', 'z', 'x']) || _.isEqual(p, ['k', 'y', 'x', 'z']))
})
答案 1 :(得分:-1)
如果你需要拓扑排序的行为,我在github上的图形js库确实有这种类型的实现:
https://github.com/chen0040/js-graph-algorithms
图表算法库中进行顶级排序的示例代码如下:
var jsgraphs = require('js-graph-algorithms');
var dag = new jsgraphs.DiGraph(7);
dag.addEdge(0, 5); // edge point from vertex 0 to 5
dag.addEdge(0, 2);
dag.addEdge(0, 1);
dag.addEdge(3, 6);
dag.addEdge(3, 5);
dag.addEdge(3, 4);
dag.addEdge(5, 4);
dag.addEdge(6, 4);
dag.addEdge(6, 0);
dag.addEdge(3, 2);
dag.addEdge(1, 4);
var ts = new jsgraphs.TopologicalSort(dag);
var order = ts.order();
console.log(order); // display array which is the topological sort order
var dag = new jsgraphs.DiGraph(7);
dag.addEdge(0, 5); // edge point from vertex 0 to 5
dag.addEdge(0, 2);
dag.addEdge(0, 1);
dag.addEdge(3, 6);
dag.addEdge(3, 5);
dag.addEdge(3, 4);
dag.addEdge(5, 4);
dag.addEdge(6, 4);
dag.addEdge(6, 0);
dag.addEdge(3, 2);
dag.addEdge(1, 4);
var ts = new jsgraphs.TopologicalSort(dag);
var order = ts.order();
console.log(order); // display array which is the topological sort order