我需要订购一个由名称和依赖列表(由名称组成)组成的对象数组。
这个数组的一个例子可能是:
[
{ name: 'a', requires: ['b', 'c'] },
{ name: 'b', requires: ['c'] },
{ name: 'c', requires: [] },
]
我希望对这个数组进行排序,以便需要一组特定依赖项的项目位于其所需的依赖项之后。
该数组实际上可以包含更多项目,如果排序函数在循环依赖的情况下抛出错误,我没关系。
示例输出:
[
{ name: 'c', requires: [] }, // first, no dependencies, and required by both the others
{ name: 'b', requires: ['c'] }, // second, because it needs `c` first
{ name: 'a', requires: ['b', 'c'] }, // last, because requires both the others
]
最简洁的方法是什么?
答案 0 :(得分:8)
您可以尝试以下(更改测试用例以支持更多可能的组合)
var arr = [
{ name: 'd', requires: ['a', 'c'] },
{ name: 'a', requires: ['b', 'c'] },
{ name: 'b', requires: ['c'] },
{ name: 'e', requires: ['d'] },
{ name: 'c', requires: [] },
];
var map = {}; // Creates key value pair of name and object
var result = []; // the result array
var visited = {}; // takes a note of the traversed dependency
arr.forEach(function(obj){ // build the map
map[obj.name] = obj;
});
arr.forEach(function(obj){ // Traverse array
if(!visited[obj.name]) { // check for visited object
sort_util(obj);
}
});
// On visiting object, check for its dependencies and visit them recursively
function sort_util(obj){
visited[obj.name] = true;
obj.requires.forEach(function(dep){
if(!visited[dep]) {
sort_util(map[dep]);
}
});
result.push(obj);
}
console.log(result);

答案 1 :(得分:1)
更新:感谢Nina Scholz,我更新了代码,以便sort
能够正常工作
这可能会起到作用。
背后的想法是,使用sort
并检查元素a
是否符合元素b
的要求。如果是这样,我们可以假设a
应该在b
之前。
但我不是百分百肯定,我只是检查了你的例子和@nikhilagw的例子。我可能忘记了什么。如果有效,请告诉我!
对于每个元素,我还继承了所有依赖项。
const list = [
{ name: 'b', requires: ['c'] },
{ name: 'e', requires: ['d'] },
{ name: 'd', requires: ['a', 'c'] },
{ name: 'c', requires: [] },
{ name: 'a', requires: ['b', 'c'] },
];
// indexed by name
const mapped = list.reduce((mem, i) => {
mem[i.name] = i;
return mem;
}, {});
// inherit all dependencies for a given name
const inherited = i => {
return mapped[i].requires.reduce((mem, i) => {
return [ ...mem, i, ...inherited(i) ];
}, []);
}
// order ...
const ordered = list.sort((a, b) => {
return !!~inherited(b.name).indexOf(a.name) ? -1 : 1;
})
console.log(ordered);
答案 2 :(得分:0)
此提案查找以前的元素,并检查实际元素是否具有之前排序的所需要求。
如果找到所有要求,则将对象拼接到索引。
function order(array) {
var i = 0,
j,
temp;
while (i < array.length) {
temp = array.slice(0, i);
for (j = i; j < array.length; j++) {
if (array[j].requires.every(n => temp.some(({ name }) => n === name))) {
array.splice(i++, 0, array.splice(j, 1)[0]);
break;
}
}
}
return array;
}
var array = [{ name: 'd', requires: ['a', 'c'] }, { name: 'a', requires: ['b', 'c'] }, { name: 'b', requires: ['c'] }, { name: 'e', requires: ['d'] }, { name: 'c', requires: [] }];
console.log(order(array));
.as-console-wrapper { max-height: 100% !important; top: 0; }