Javascript 相互依赖的元素的排序数组
我有点不知所措。我有一个元素数组,它将用于计算当前元素的值,具体取决于它之前的链中的元素。(考虑一个时间线,其中元素的日期相对于其他元素为+/-n天。) 问题是,只有一个元素具有初始值[ie start date],它之前的其他元素(prtcxxx系列)将从中减去,然后彼此减去,它之后的元素(testxxxx、reportxxxx、issuexxx)将添加到它,然后在链中彼此相加。 我尝试使用规则创建array.sort以允许这种排序,但它不起作用。 我还尝试使用if/elseif->outputArr.splice创建自己的排序工作流,但也没有成功:/Javascript 相互依赖的元素的排序数组,javascript,arrays,sorting,Javascript,Arrays,Sorting,我有点不知所措。我有一个元素数组,它将用于计算当前元素的值,具体取决于它之前的链中的元素。(考虑一个时间线,其中元素的日期相对于其他元素为+/-n天。) 问题是,只有一个元素具有初始值[ie start date],它之前的其他元素(prtcxxx系列)将从中减去,然后彼此减去,它之后的元素(testxxxx、reportxxxx、issuexxx)将添加到它,然后在链中彼此相加。 我尝试使用规则创建array.sort以允许这种排序,但它不起作用。 我还尝试使用if/elseif->outpu
// array columns:
// [elementID, I_depend_on_this_elementID, my_value, calculated_value]
let arrayMe = [
["report0700", "report0500"],
["issue0200", "report1000"],
["report1000", "report0900"],
["report0900", "report0800"],
["issue0230", "report1000"],
["issue0000", ""],
["issue0100", ""],
["issue0110", ""],
["issue0240", "issue0240"],
["test0100", "test0100",10,10], // this element will actually start the chain for everything else
["protc0000", ""],
["protc0300", "protc0500"],
["report0600", "protc0100"],
["report0800", "report0700"],
["issue0120", ""],
["issue0220", ""],
["protc0200", "protc0300"],
["protc0600", "protc0100"],
["protc0100", "protc0200"],
["protc0700", "protc0800"],
["protc0500", "protc0700"],
["protc0400", "protc0500"],
["protc1000", "test0100"],
["protc0900", "protc1000"],
["protc0800", "protc0900"],
["test0000", ""],
["test0400", "test0300"],
["test0300", "test0200"],
["test0200", "test0100"],
["test0600", "test0500"],
["test0700", "test0500"],
["test0500", "test0400"],
["report0000", ""],
["report0400", "report0300"],
["report0500", "report0300"],
["report0300", "report0200"],
["report0200", "report0100"],
["report0100", "test0400"],
];
arrayMe.sort((a, b) => {
console.log(a[0], " -- ", b[1]);
if (a[0] == b[1]) {return 1;} // a before b, because b depends on a
if (a[1] == b[0]) {return -1;} // b before a, because a depends on b
if (a[1] == a[0]) {return 1;} // a in front, because it depends only on itself and others will depend on it
if (a[1] == "") {return 0;} // a can be wherever, because it doesn't depend on anyone, nor anyone will depend on it
return 0;
});
console.log(arrayMe);
以及我自己的排序尝试(我想需要多次重复/递归才能完成排序):
所有数组元素都不会导致循环引用
上面的模型被简化了,实际上我将有一个动态ish对象,其中包含如下元素,其中到期日将根据其他元素计算:
report0700: {
title: "A task to be performed by specific date, 7 days after report0500",
relative_to: "report0500",
delta: +7,
due_date: null // report0500.due_date = 03 DEC 2020 + delta, -> report0700.due_date = 10 DEC 2020
},
report0800: {
title: "another to be performed by specific date, 14 days after report0700",
relative_to: "report0700",
delta: +14,
due_date: null // report0700.due_date = 10 DEC 2020 + delta, -> report0800.due_date = 24 DEC 2020
},
如有任何建议,将不胜感激
编辑:
上面有两个尝试排序的示例:
arrayMe.sort((a,b)=>{…
和
arrayMe.forEach(函数(a){…
按元素相互依赖的方式排序后的预期元素顺序如下所示
let arrayMe = [
["test0100", "test0100", 10, 10], // this element will actually start the chain for everything else
["issue0240", "issue0240"], // depends on itself, just dump it in front
["issue0000", ""], // does not depend on any other, just dump it anywhere
["issue0100", ""], // does not depend on any other, just dump it anywhere
["issue0110", ""], // does not depend on any other, just dump it anywhere
["protc0000", ""], // does not depend on any other, just dump it anywhere
["issue0120", ""], // does not depend on any other, just dump it anywhere
["issue0220", ""], // does not depend on any other, just dump it anywhere
["test0000", ""], // does not depend on any other, just dump it anywhere
["report0000", ""], // does not depend on any other, just dump it anywhere
// protcxxxx series, starts by depending on [test0100]
// from here on, the rule is simple:
// element with name in [column1] comes after element named in [column2]
["protc1000", "test0100"], // ie ["protc1000", "test0100"] needs to be positioned anywhere after element ["test0100", "test0100", 10, 10]
["protc0900", "protc1000"],
["protc0800", "protc0900"],
["protc0700", "protc0800"],
["protc0500", "protc0700"],
["protc0400", "protc0500"],
["protc0300", "protc0500"],
["protc0200", "protc0300"],
["protc0100", "protc0200"],
["protc0600", "protc0100"],
["report0600", "protc0100"],
// testxxxx series, starts by depending on [test0100] and can be mangled in between protcxxxx nodes
["test0200", "test0100"],
["test0300", "test0200"],
["test0400", "test0300"],
["test0500", "test0400"],
["test0600", "test0500"],
["test0700", "test0500"],
// reportxxxx series, starts by depending on [test0400]
["report0100", "test0400"],
["report0200", "report0100"],
["report0300", "report0200"],
["report0400", "report0300"],
["report0500", "report0300"],
["report0700", "report0500"],
["report0800", "report0700"],
["report0900", "report0800"],
["report1000", "report0900"],
// issuetxxxx series, starts by depending on [report1000]
["issue0200", "report1000"],
["issue0230", "report1000"],
];
我将采取的方法是创建一个依赖项索引。该索引将递归地包含所有依赖项的列表。然后将父项排序在子项之前
let arrayMe = [
["report0700", "report0500"],
["issue0200", "report1000"],
["report1000", "report0900"],
["report0900", "report0800"],
["issue0230", "report1000"],
["issue0000", ""],
["issue0100", ""],
["issue0110", ""],
["issue0240", "issue0240"],
["test0100", "test0100", 10, 10], // this element will actually start the chain for everything else
["protc0000", ""],
["protc0300", "protc0500"],
["report0600", "protc0100"],
["report0800", "report0700"],
["issue0120", ""],
["issue0220", ""],
["protc0200", "protc0300"],
["protc0600", "protc0100"],
["protc0100", "protc0200"],
["protc0700", "protc0800"],
["protc0500", "protc0700"],
["protc0400", "protc0500"],
["protc1000", "test0100"],
["protc0900", "protc1000"],
["protc0800", "protc0900"],
["test0000", ""],
["test0400", "test0300"],
["test0300", "test0200"],
["test0200", "test0100"],
["test0600", "test0500"],
["test0700", "test0500"],
["test0500", "test0400"],
["report0000", ""],
["report0400", "report0300"],
["report0500", "report0300"],
["report0300", "report0200"],
["report0200", "report0100"],
["report0100", "test0400"],
];
// Calculate dependents
let dep1 = arrayMe.reduce((idx, item) => {
if (item[1] != "") {
idx[item[1]] = idx[item[1]] ? idx[item[1]] : [];
idx[item[1]].push(item[0])
};
return idx
}, {});
// Calculate deep dependents
let m = true;
while (m) {
m = false;
for (const p in dep1) {
let itemlen = dep1[p].length;
for (let ix = 0; ix < itemlen; ix++) {
if (undefined != dep1[dep1[p][ix]]) {
let parent = dep1[dep1[p][ix]];
for (let iy = 0; iy < parent.length; iy++) {
if (dep1[p].indexOf(parent[iy]) == -1) {
dep1[p].push(parent[iy]);
m = true;
}
}
}
}
}
}
arrayMe.sort((a, b) => {
let da = dep1[a[0]];
let db = dep1[b[0]];
if (da != undefined && da.indexOf(b[0]) != -1) {
return -1; // b is a dependent of a
}
if (db != undefined && db.indexOf(a[0]) != -1) {
return 1; // a is a dependent of b
}
let ca = da ? da.length : 0;
let cb = db ? db.length : 0;
return cb - ca;
});
让数组=[
[“报告0700”、“报告0500”],
[“发布2200”、“报告1000”],
[“报告1000”、“报告0900”],
[“报告0900”、“报告0800”],
[“发布2300”、“报告1000”],
[“发行000”和“]”,
[“issue0100”、“”],
[“issue0110”和“]”,
[“issue0240”、“issue0240”],
[“test0100”、“test0100”、10、10],//这个元素实际上会启动其他所有元素的链
[“protc0000”和“,”],
[“protc0300”、“protc0500”],
[“report0600”、“protc0100”],
[“报告0800”、“报告0700”],
[“发行1120”和“]”,
[“发行2220”和“,”],
[“protc0200”、“protc0300”],
[“protc0600”、“protc0100”],
[“protc0100”、“protc0200”],
[“protc0700”、“protc0800”],
[“protc0500”、“protc0700”],
[“protc0400”、“protc0500”],
[“protc1000”、“test0100”],
[“protc0900”、“protc1000”],
[“protc0800”、“protc0900”],
[“test0000”,“test0000”],
[“test0400”、“test0300”],
[“test0300”、“test0200”],
[“test0200”、“test0100”],
[“test0600”、“test0500”],
[“test0700”、“test0500”],
[“test0500”、“test0400”],
[“report0000”、“”],
[“报告0400”、“报告0300”],
[“报告0500”、“报告0300”],
[“报告0300”、“报告0200”],
[“报告0200”、“报告0100”],
[“report0100”、“test0400”],
];
//计算家属
让dep1=arrayMe.reduce((idx,item)=>{
如果(项目[1]!=“”){
idx[项目[1]]=idx[项目[1]]?idx[项目[1]]:[];
idx[项目[1]]。推送(项目[0])
};
返回idx
}, {});
//计算深度依赖项
设m=true;
while(m){
m=假;
用于(部门1中的常数p){
设itemlen=dep1[p]。长度;
for(设ix=0;ix{
设da=dep1[a[0]];
设db=dep1[b[0]];
如果(da!=未定义和&da.indexOf(b[0])!=-1){
return-1;//b是a的依赖项
}
如果(db!=未定义&&db.indexOf(a[0])!=-1){
返回1;//a是b的依赖项
}
设ca=da?da。长度:0;
设cb=db?db。长度:0;
返回cb-ca;
});
更新了以将循环节点的修复程序拉入一个单独的函数中。这将保持主代码的整洁;而且该修复程序可能会被丢弃
我可能会把它变成一棵树,或者更确切地说是一片森林,一组树,然后对这些树进行预定访问。这是一种方法:
constmakeforest=(根,xs)=>
过滤器(([\ux,parent])=>parent==root)
.地图(
([id,parent,…rest])=>[id,parent,makeForest(id,xs),…rest]
)
const preorder=([id,父,子,…rest])=>
[[id,parent,…rest],…(children | |[]).flatMap(预排序)]
常数依赖顺序=(xs)=>
makeForest(“”,xs).flatMap(预订单)
让arrayMe=[“report0700”、“report0500”]、[“issue0200”、“report1000”]、[“report1000”、“report0900”]、[“report0900”、“report0800”]、[“issue0230”、“report1000”]、[“issue0000”、[“issue0100”、[“issue0240”]、[“issue0240”]、[“test0100”、“test0100”、10/*此元素实际上将启动其他所有内容的链*/],[“protc0000”、[“protc0300”、“protc0500”]、[“report0600”、“protc0100”]、[“report0800”、“report0700”]、[“issue0120”、[“issue0220”、[“protc0200”、“protc0300”]、[“protc0600”、“protc0100”]、[“protc0100”、“protc0200”]、[“protc0700”、“protc0800”]、[“protc0500”、“protc0400”、“protc0500”]、[“protc0600”、[“protc0000”、“test0100”][“protc0900”、“protc1000”]、[“protc0800”、“protc0900”]、[“test0000”、[“test0400”、“test0300”]、[“test0300”、“test0200”]、[“test0200”、“test0100”]、[“test0600”、“test0500”]、[“test0700”、“test0500”]、[“test0500”、“test0400”]、[“report0000”、“report0400”、“report0300”]、[“report0500”、“report0300”]、[“report0500”、“report0300”]、[“report0300”、[“report0500”、[“report0300”]、[“report0300”]、[“report0300”、[“report0300”]、[“report0300”]、”report0200、report0100“]、[“report0100”、“test0400”];
//将自相关节点(??!)重铸为根节点。
常数固定=(xs)=>
map(([id,parent,…rest])=>[id,parent==id?'':parent,…rest])
console.log(dependencyOrder(fix(arrayMe)))
.a
let arrayMe = [
["report0700", "report0500"],
["issue0200", "report1000"],
["report1000", "report0900"],
["report0900", "report0800"],
["issue0230", "report1000"],
["issue0000", ""],
["issue0100", ""],
["issue0110", ""],
["issue0240", "issue0240"],
["test0100", "test0100", 10, 10], // this element will actually start the chain for everything else
["protc0000", ""],
["protc0300", "protc0500"],
["report0600", "protc0100"],
["report0800", "report0700"],
["issue0120", ""],
["issue0220", ""],
["protc0200", "protc0300"],
["protc0600", "protc0100"],
["protc0100", "protc0200"],
["protc0700", "protc0800"],
["protc0500", "protc0700"],
["protc0400", "protc0500"],
["protc1000", "test0100"],
["protc0900", "protc1000"],
["protc0800", "protc0900"],
["test0000", ""],
["test0400", "test0300"],
["test0300", "test0200"],
["test0200", "test0100"],
["test0600", "test0500"],
["test0700", "test0500"],
["test0500", "test0400"],
["report0000", ""],
["report0400", "report0300"],
["report0500", "report0300"],
["report0300", "report0200"],
["report0200", "report0100"],
["report0100", "test0400"],
];
// Calculate dependents
let dep1 = arrayMe.reduce((idx, item) => {
if (item[1] != "") {
idx[item[1]] = idx[item[1]] ? idx[item[1]] : [];
idx[item[1]].push(item[0])
};
return idx
}, {});
// Calculate deep dependents
let m = true;
while (m) {
m = false;
for (const p in dep1) {
let itemlen = dep1[p].length;
for (let ix = 0; ix < itemlen; ix++) {
if (undefined != dep1[dep1[p][ix]]) {
let parent = dep1[dep1[p][ix]];
for (let iy = 0; iy < parent.length; iy++) {
if (dep1[p].indexOf(parent[iy]) == -1) {
dep1[p].push(parent[iy]);
m = true;
}
}
}
}
}
}
arrayMe.sort((a, b) => {
let da = dep1[a[0]];
let db = dep1[b[0]];
if (da != undefined && da.indexOf(b[0]) != -1) {
return -1; // b is a dependent of a
}
if (db != undefined && db.indexOf(a[0]) != -1) {
return 1; // a is a dependent of b
}
let ca = da ? da.length : 0;
let cb = db ? db.length : 0;
return cb - ca;
});