Javascript 按父级排序(拓扑排序)和数组中元素的重要性

Javascript 按父级排序(拓扑排序)和数组中元素的重要性,javascript,arrays,sorting,lodash,topological-sort,Javascript,Arrays,Sorting,Lodash,Topological Sort,我有一个数组,其中一些元素依赖于其他元素 因此,我需要按重要性(父项的依赖性)排序,将其存储在数据库中,并用相应的父项id替换所有子项的parent属性 数组示例: [ { "id": 1, "email": "a@b.com", // unique "parent": "c@b.com" // is nullable }, { "id": 2, "email": "b@b.com",

我有一个数组,其中一些元素依赖于其他元素

因此,我需要按重要性(父项的依赖性)排序,将其存储在数据库中,并用相应的父项
id
替换所有子项的
parent
属性

数组示例:

[
    {
        "id": 1,
        "email": "a@b.com", // unique
        "parent": "c@b.com" // is nullable
    },
    {
        "id": 2,
        "email": "b@b.com",
        "parent": null
    },
    {
        "id": 3,
        "email": "c@b.com",
        "parent": "b@b.com"
    },
    {
        "id": 4,
        "email": "d@b.com",
        "parent": "a@b.com"
    },
    ...
]
let users = [
{
    "id": 1,
    "email": "a@b.com", // unique
    "parent": "c@b.com" // is nullable
},
{
    "id": 2,
    "email": "b@b.com",
    "parent": null
},
{
    "id": 3,
    "email": "c@b.com",
    "parent": "b@b.com"
},
{
    "id": 4,
    "email": "d@b.com",
    "parent": "a@b.com"
}
];

users = users.map(user => {
    user.parent = _.findIndex(users, i => user.parent === i.email);
    return user;
});
依赖关系的图形示例:

[
    {
        "id": 1,
        "email": "a@b.com", // unique
        "parent": "c@b.com" // is nullable
    },
    {
        "id": 2,
        "email": "b@b.com",
        "parent": null
    },
    {
        "id": 3,
        "email": "c@b.com",
        "parent": "b@b.com"
    },
    {
        "id": 4,
        "email": "d@b.com",
        "parent": "a@b.com"
    },
    ...
]
let users = [
{
    "id": 1,
    "email": "a@b.com", // unique
    "parent": "c@b.com" // is nullable
},
{
    "id": 2,
    "email": "b@b.com",
    "parent": null
},
{
    "id": 3,
    "email": "c@b.com",
    "parent": "b@b.com"
},
{
    "id": 4,
    "email": "d@b.com",
    "parent": "a@b.com"
}
];

users = users.map(user => {
    user.parent = _.findIndex(users, i => user.parent === i.email);
    return user;
});

预期结果: 按依赖项(父项)排序:

设置我正在使用的相应父级
id
(但不按父级排序:父级、子级、孙级……):

[
    {
        "id": 1,
        "email": "a@b.com", // unique
        "parent": "c@b.com" // is nullable
    },
    {
        "id": 2,
        "email": "b@b.com",
        "parent": null
    },
    {
        "id": 3,
        "email": "c@b.com",
        "parent": "b@b.com"
    },
    {
        "id": 4,
        "email": "d@b.com",
        "parent": "a@b.com"
    },
    ...
]
let users = [
{
    "id": 1,
    "email": "a@b.com", // unique
    "parent": "c@b.com" // is nullable
},
{
    "id": 2,
    "email": "b@b.com",
    "parent": null
},
{
    "id": 3,
    "email": "c@b.com",
    "parent": "b@b.com"
},
{
    "id": 4,
    "email": "d@b.com",
    "parent": "a@b.com"
}
];

users = users.map(user => {
    user.parent = _.findIndex(users, i => user.parent === i.email);
    return user;
});
附言: 在这种情况下,
重要性
概念指的是
父级
级别。 所以,首先我需要父母,然后是孩子,孙子,等等


很抱歉,如果这个线程解释得不好,如果您有疑问,我将寻找最好的方式来表达这个想法。

您可以使用递归函数

const数据=[{
“id”:1,
“电子邮件”:a@b.com“,//唯一
“父项”:c@b.com“//可为空
},
{
“id”:2,
“电子邮件”:b@b.com",
“父项”:空
},
{
“id”:3,
“电子邮件”:c@b.com",
“父项”:b@b.com"
},
{
“id”:4,
“电子邮件”:d@b.com",
“父项”:a@b.com"
},
]
常量顺序=(arr,级别)=>{
const children=arr.filter(e=>e.parent==level);//获取具有相同父级(level)的元素
const parent=arr.find(e=>e.email==level);//获取父项
返回长度
? [
…children.map(e=>
({……e,
parent:parent?parent.id:null//将父项更新为id而不是电子邮件
})),
…order(arr,children[0].email)//调用与当前子数组的第一个子元素的email相同的函数,它将成为父元素
] 
:children//否则返回数组
}
常量结果=顺序(数据,空)

console.log(result)
我将首先生成一个新的输入,用
父id替换
父电子邮件
,并生成与它们所属的树相关的节点级别的新属性。然后,我们可以按照这个
级别
属性对节点进行排序,在相同的
级别
上,我们按照
id
对节点进行排序

const输入=[
{“id”:1,“电子邮件”:a@b.com,“父项”:c@b.com"},
{“id”:2,“电子邮件”:b@b.com,“父级”:null},
{“id”:3,“电子邮件”:c@b.com,“父项”:b@b.com"},
{“id”:4,“电子邮件”:d@b.com,“父项”:a@b.com"},
{“id”:5,“电子邮件”:x@b.com,“父项”:b@b.com"},
{“id”:6,“电子邮件”:z@b.com,“父项”:x@b.com"},
{“id”:7,“电子邮件”:y@b.com,“父级”:null},
{“id”:8,“电子邮件”:m@b.com,“父项”:y@b.com"}
];
const findParent=(mail)=>input.find(x=>x.email==mail);
const getLevel=(邮件,lvl)=>
{    
返回邮件?getLevel(findParent(mail).parent,lvl+1):lvl;
}
让newInput=input.map({id,email,parent})=>
{
返回{
id:id,
电邮:电邮,,
父项:findParent(父项)?findParent(父项)。id:null,
lvl:getLevel(父级,0)
};
});
让sortedInput=newInput.sort((a,b)=>
{
返回(a.lvl-b.lvl)?a.lvl-b.lvl:a.id-b.id;
});

控制台日志(sortedInput)是一种迭代方法(与提供的递归解决方案相反),您可以使用它来实现您的结果。基本上,从查找根元素开始,然后遍历原始数组,查找当前元素作为其父元素的元素

要实现用ID替换父电子邮件,只需保留父名称到ID的映射:

var数据=[{
“id”:1,
“电子邮件”:a@b.com“,//唯一
“父项”:c@b.com“//可为空
}, {
“id”:2,
“电子邮件”:b@b.com",
“父项”:空
}, {
“id”:3,
“电子邮件”:c@b.com",
“父项”:b@b.com"
}, {
“id”:4,
“电子邮件”:d@b.com",
“父项”:a@b.com"
}]
//将电子邮件地址映射到ID
var映射=数据减少((累计,el)=>{
累计[电子邮件]={
id:el.id
}
返回累计;
}, {});
var[root]=data.filter(el=>!el.parent);
var用户=[root];
var-cur;
儿童;
while(users.lengthel.parent==cur.email);
children.forEach(el=>{
用户推送({
id:el.id,
电子邮件:el.email,
父:映射[el.parent].id
});
});
}

console.log(用户)
您所说的“重要性”是什么意思?哪一个元素是“最重要的”?@Qurimmo问得好,我刚刚为你的问题添加了答案。顺序是父母、子女、孙子女等。在您的示例中,
父母
引用父母的
电子邮件
属性,但在所需的输出中,他们切换到
id
。这是故意的吗?编辑:没关系,我看到你提到过:“用各自的Id替换孩子们。”@TylerRoper在几秒钟内我说“所以,我需要按重要性排序(父项的依赖关系)存储在数据库中,并用各自的Id替换孩子们。”其中,各自的Id是你想要一棵树的父项。您所描述的内容听起来可能像是广度优先遍历,也可能像是预排序、深度优先遍历。你的样品太小,不知道你在找什么。请使用这些术语进行搜索。这看起来像我想要的,但它没有按父级(父级、子级、孙级…)对元素进行排序:请看这里:哦,那么您希望元素首先没有父级(可能按id排序),然后是一级节点、二级节点,等等。。。(如果我们认为这是一棵树)?太感谢了,这项工作!我尝试使用2.5毫米的元素;)