好吧,我有一个对象数组,其中某些元素取决于其他元素。
因此,我需要按重要性(父级依赖性)对其进行排序,以将其存储在数据库中,并用相应的父级parent
替换所有子级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"
},
...
]
依赖关系的图形示例:
预期结果: 按依赖关系(父项)排序:
[
{
"id": 2,
"email": "b@b.com",
"parent": null
},
{
"id": 3,
"email": "c@b.com",
"parent": 2
},
{
"id": 1,
"email": "a@b.com",
"parent": 3
},
{
"id": 4,
"email": "d@b.com",
"parent": 1
},
...
]
要设置我正在使用的各个父级id
(但按父级排序:父级,子级,子级...):
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;
});
P.S:
在这种情况下,importance
概念是指parent
级别。
所以,首先我需要父母,然后是孩子,孙子等等……
很抱歉,如果该主题的解释不充分,如果您有疑问,我将寻求表达此想法的最佳方法。
答案 0 :(得分:2)
您可以使用递归函数
const data = [{
"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"
},
]
const order = (arr, level) => {
const children = arr.filter(e => e.parent === level); // get the elements that have the same parent ( level )
const parent = arr.find(e => e.email === level); // get the parent
return children.length
? [
...children.map(e =>
({ ...e,
parent: parent ? parent.id : null // update the parent to the id instead of email
})),
...order(arr, children[0].email) // call the same function with the email of the first child of the current children array, it will become a parent
]
: children // otherwise return the array
}
const result = order(data, null)
console.log(result)
答案 1 :(得分:2)
我将通过首先生成一个新输入(用parent email
替换parent id
以及与它们所属的树相关的节点级别的新属性)来解决这个问题。然后,我们可以通过此level
属性对节点进行排序,并在相等的level
上通过id
进行排序。
const input = [
{"id": 1, "email": "a@b.com", "parent": "c@b.com"},
{"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"},
{"id": 5, "email": "x@b.com", "parent": "b@b.com"},
{"id": 6, "email": "z@b.com", "parent": "x@b.com"},
{"id": 7, "email": "y@b.com", "parent": null},
{"id": 8, "email": "m@b.com", "parent": "y@b.com"}
];
const findParent = (mail) => input.find(x => x.email === mail);
const getLevel = (mail, lvl) =>
{
return mail ? getLevel(findParent(mail).parent, lvl + 1) : lvl;
}
let newInput = input.map(({id, email, parent}) =>
{
return {
id: id,
email: email,
parent: findParent(parent) ? findParent(parent).id : null,
lvl: getLevel(parent, 0)
};
});
let sortedInput = newInput.sort((a, b) =>
{
return (a.lvl - b.lvl) ? a.lvl - b.lvl : a.id - b.id;
});
console.log(sortedInput);
答案 2 :(得分:1)
下面是一种迭代方法(与提供的递归解决方案相对),您可以用来实现结果。基本上,从查找根元素开始,然后遍历原始数组,查找以当前元素为父元素的元素。
要用ID替换父电子邮件,只需将父名称映射到ID:
var data = [{
"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"
}]
//Map email addresses to IDs
var map = data.reduce((accum, el) => {
accum[el.email] = {
id: el.id
}
return accum;
}, {});
var [root] = data.filter(el => !el.parent);
var users = [root];
var cur;
var children;
while (users.length < data.length) {
cur = users[users.length - 1];
//Find elments that have cur as parent
children = data.filter(el => el.parent === cur.email);
children.forEach(el => {
users.push({
id: el.id,
email: el.email,
parent: map[el.parent].id
});
});
}
console.log(users)