JavaScript-根据依赖关系树进行排序

JavaScript-根据依赖关系树进行排序,javascript,arrays,typescript,sorting,topological-sort,Javascript,Arrays,Typescript,Sorting,Topological Sort,我必须展示一组相互依赖的图像。比如说 Image A depends on no one Image B depends on A Image C depends on A and B Image D depends on F Image E depends on D and C Image F depends on no one 我有一个javascript对象,如下所示: const imageDependencies = { A: [], B: ['A'],

我必须展示一组相互依赖的图像。比如说

 Image A depends on no one
 Image B depends on A
 Image C depends on A and B
 Image D depends on F
 Image E depends on D and C
 Image F depends on no one
我有一个javascript对象,如下所示:

const imageDependencies = {
    A: [],
    B: ['A'],
    C: ['A', 'B'],
    D: ['F'],
    E: ['D', 'C'],
    F: []
}
let names = Object.keys(imageDependencies);
names.sort((a,b) => {
    if(imageDependencies [a].includes(b)) return 1
    else return -1
})
我需要将所有图像名称按其依赖项排序。此示例的结果可能是以下任一结果:

//首先得到A的值。一旦得到了,就可以得到B的值。一旦得到了A和B的值,就可以得到C,依此类推
结果_1=[A,B,C,F,D,E]
//这可能是另一个正确的结果
结果_2=[A,F,D,B,C,E]
我尝试过像这样使用
Array.sort()
函数:

const imageDependencies = {
    A: [],
    B: ['A'],
    C: ['A', 'B'],
    D: ['F'],
    E: ['D', 'C'],
    F: []
}
let names = Object.keys(imageDependencies);
names.sort((a,b) => {
    if(imageDependencies [a].includes(b)) return 1
    else return -1
})
但它不能正常工作

如何做到这一点?

您可以对添加的键进行检查,并检查实际依赖项是否已将所有元素添加到集合中。然后添加此键,否则继续。继续,直到阵列中不再有项目

var依赖项={A:[],B:['A'],C:['A',B'],D:['F'],E:['D',C'],F:[],G:['H'],H:['G']},
键=对象。键(依赖项),
已使用=新设置,
结果=[],
i、 项目,长度;
做{
长度=键。长度;
i=0;
while(i

.as控制台包装{max height:100%!important;top:0;}
这里需要的是一个拓扑排序

()

我用了这个例子

作者:Shin Suzuki

const imageDependencies={
A:[],
B:[A'],
C:[A',B'],
D:[F'],
E:['D','C'],
F:[]
}
函数tsort(边){
让节点={},排序=[],访问={};
让节点=函数(id){
this.id=id;
this.after=[];
}
边缘。forEach((v)=>{
设from=v[0],to=v[1];
如果(!nodes[from])nodes[from]=新节点(from);
如果(!nodes[to])nodes[to]=新节点(to);
节点[from].after.push(to);
});
Object.key(nodes).forEach(函数访问(idstr,祖先){
让node=nodes[idstr],id=node.id;
如果(访问[idstr])返回;
如果(!Array.isArray(祖先))祖先=[];
1.push(id);
已访问[idstr]=真;
node.after.forEach(函数(afterID){
if(祖先索引of(afterID)>=0)
抛出新错误('闭合链:'+afterID+'在'+id'中);
访问(afterID.toString(),祖先.map(函数(v){return v}));
});
已排序。取消移位(id);
});
返回排序;
}
const createEdges=(dep)=>{
让结果=[]
Object.keys(dep.forEach)(key=>{
dep[key].forEach(n=>{
结果。推送([n,键])
})
})
返回结果
}
常量列表=CreateEdge(imageDependencies)
console.log(tsort(list))
我的做法是:

const imageDependencies={
A:[],
B:[“A”],
C:[“A”、“B”],
D:[“F”],
E:[“D”,“C”],
F:[]
};
让keys=Object.keys(imageDependencies),//[“A”、“B”、“C”、“D”、“E”、“F”]
输出=[];
while(键长){
用于(让我输入钥匙){
设key=key[i],/“A”
依赖项=图像依赖项[键];//[]
if(dependency.every(dependency=>output.includes(dependency)){//如果输出数组中已经存在所有依赖项
output.push(键);//将“A”按到输出
键。拼接(i,1);//从键中删除“A”
}
}
}

console.log(“output=”,output)这里是使用Array.prototype.reduce()的另一个漏洞

const imageDependencies={
A:[],
B:[A'],
C:[A',B'],
D:[F'],
E:['D','C'],
F:[]
}
常量imageDependenciesBad={
A:[“X”],
B:[A'],
C:[A',B'],
D:[F'],
E:['D','C'],
F:[]
}
常量排序=(名称、对象、开始、深度=0)=>{
const processed=names.reduce((a,b,i)=>{
if(obj[b].every(Array.prototype.includes,a))a.push(b)
归还
},开始)
const nextNames=names.filter(n=>!processed.includes(n)),

goAgain=nextNames.length&depth
toposort
是一个非常好的库

const toposort=require(“toposort”)
常量imageDependencies={
A:[],
B:[A'],
C:[A',B'],
D:[F'],
E:['D','C'],
F:[]
}
//将依赖项拆分为对以进行拓扑排序
设deps=[]
key(imageDependencies).forEach(k=>{
imageDependencies[k].forEach(d=>{
副推力([d,k])
})
})
toposort.array(Object.keys(imageDependencies),deps)
//->[“A”、“B”、“C”、“F”、“D”、“E”]

您可以像手动操作一样以编程的方式实现它。我投了赞成票。:)它可以通过一个抛出错误的控件来改进,而不是无限期地循环?也许还可以增加一个
outputSet:Set
来处理
imageDependencies
很大的情况。哦,是的,可以通过failsaf来改进是的,选项,花哨的功能等等,但我把重点放在了核心问题上:)谢谢你的投票!看起来,你有一个类似的想法:-)如果循环{a:['B'],B:['a'],C:[]}它将永远不会结束。显然,它需要有效的依赖项。
{a:['B'],B:['a']}
无效,这是一个依赖循环。如果出现循环{a:['B'],B:['a'],C:[]}@NaorTedgi,它将永远不会结束,谢谢你指出。现在它在末尾添加了这些项。请参见编辑。我们应该支持无效的输入和依赖循环吗?因为
{a:['B'],B:['a']}
是一种依赖关系loop@JeremyThille如果没有指定的话,也不一定。但是如果没有循环的话,也不会有什么坏处。当有循环的时候,就没有明确的顺序,这会使顺序变得模棱两可。我不认为