Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/402.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 相互依赖的元素的排序数组_Javascript_Arrays_Sorting - Fatal编程技术网

Javascript 相互依赖的元素的排序数组

Javascript 相互依赖的元素的排序数组,javascript,arrays,sorting,Javascript,Arrays,Sorting,我有点不知所措。我有一个元素数组,它将用于计算当前元素的值,具体取决于它之前的链中的元素。(考虑一个时间线,其中元素的日期相对于其他元素为+/-n天。) 问题是,只有一个元素具有初始值[ie start date],它之前的其他元素(prtcxxx系列)将从中减去,然后彼此减去,它之后的元素(testxxxx、reportxxxx、issuexxx)将添加到它,然后在链中彼此相加。 我尝试使用规则创建array.sort以允许这种排序,但它不起作用。 我还尝试使用if/elseif->outpu

我有点不知所措。我有一个元素数组,它将用于计算当前元素的值,具体取决于它之前的链中的元素。(考虑一个时间线,其中元素的日期相对于其他元素为+/-n天。) 问题是,只有一个元素具有初始值[ie start date],它之前的其他元素(prtcxxx系列)将从中减去,然后彼此减去,它之后的元素(testxxxx、reportxxxx、issuexxx)将添加到它,然后在链中彼此相加。 我尝试使用规则创建array.sort以允许这种排序,但它不起作用。 我还尝试使用if/elseif->outputArr.splice创建自己的排序工作流,但也没有成功:/

// 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;
});