[英]Find the highest object in array tree of nested children
I have an array of nested regions that look like this:我有一组嵌套区域,如下所示:
The array itself:数组本身:
[
{
"key": 10,
"title": "Egypt",
"parent_key": null,
"children": [
{
"key": 1,
"title": "Zone 1",
"parent_key": 10,
"children": [
{
"key": 3,
"title": "Tagamo3",
"parent_key": 1,
"children": []
},
{
"key": 7,
"title": "Giza",
"parent_key": 1,
"children": []
},
{
"key": 8,
"title": "Helwan",
"parent_key": 1,
"children": []
},
{
"key": 11,
"title": "Fayoum",
"parent_key": 1,
"children": []
}
]
},
{
"key": 2,
"title": "Zone 2",
"parent_key": 10,
"children": [
{
"key": 4,
"title": "Gesr ElSuis",
"parent_key": 2,
"children": [
{
"key": 12,
"title": "test",
"parent_key": 4,
"children": []
}
]
},
{
"key": 5,
"title": "Delta",
"parent_key": 2,
"children": []
},
{
"key": 6,
"title": "Mohandeseen",
"parent_key": 2,
"children": []
},
{
"key": 9,
"title": "Down Town",
"parent_key": 2,
"children": []
}
]
}
]
}
]
I want to return to the highest region in a given input我想返回给定输入中的最高区域
Examples:例子:
First it helps to turn your tree structure into a map of descendant ids, recursively:首先,它有助于将您的树结构递归地转换为后代 id 的 map:
const descendantsMap = new Map<number, Set<number>>();
function walk(tree: Tree) {
const s: Set<number> = new Set();
descendantsMap.set(tree.key, s);
for (const t of tree.children) {
walk(t);
s.add(t.key);
descendantsMap.get(t.key)?.forEach(v => s.add(v));
}
}
arr.forEach(walk);
We are building up a Map
from each key
in your tree structure to a Set
of the key
s of its descendants.我们正在构建一个
Map
从树结构中的每个key
到其后代的一Set
key
。 The walk()
function is recursive, and we merge the descendants for the children
of each node into the descendants for the current node. walk()
function 是递归的,我们将每个节点的children
节点的后代合并到当前节点的后代中。
Let's make sure it looks right:让我们确保它看起来正确:
console.log(descendantsMap);
/* Map (12) {
10 => Set (11) {1, 3, 7, 8, 11, 2, 4, 12, 5, 6, 9},
1 => Set (4) {3, 7, 8, 11},
3 => Set (0) {},
7 => Set (0) {},
8 => Set (0) {},
11 => Set (0) {},
2 => Set (5) {4, 12, 5, 6, 9},
4 => Set (1) {12},
12 => Set (0) {},
5 => Set (0) {},
6 => Set (0) {},
9 => Set (0) {}
} */
Yes.是的。 You can see how now we have a quick mapping from each
key
to the set of key
s in its descendant subtree.您可以看到现在我们如何快速映射从每个
key
到其后代子树中的key
集。
Now to get the "highest" entries in an array (I would call these the "shallowest" since they are closest to the root), we find all the descendants of all the elements in the array and then filter these out of the array:现在要获取数组中的“最高”条目(我将它们称为“最浅”,因为它们最接近根),我们找到数组中所有元素的所有后代,然后将它们从数组中过滤掉:
const shallowest = (x: number[]): number[] => {
const descendants = new Set<number>();
for (const v of x) {
descendantsMap.get(v)?.forEach(i => descendants.add(i));
}
console.log(descendants); // just to understand what's happening
return x.filter(v => !descendants.has(v));
}
Let's test it:让我们测试一下:
console.log(shallowest([7, 1, 10]));
// descendants are {3, 7, 8, 11, 1, 2, 4, 12, 5, 6, 9}
// output [10]
console.log(shallowest([1, 2]));
// descendants are {3, 7, 8, 11, 4, 12, 5, 6, 9};
// output [1, 2]
console.log(shallowest([2, 3, 1]));
// descendants are {4, 12, 5, 6, 9, 3, 7, 8, 11};
// output [2, 1]
console.log(shallowest([1, 4]));
// descendants are {3, 7, 8, 11, 12};
// output [1, 4]
Looks good.看起来不错。 You can see that
shallowest([7, 1, 10])
first finds all the descendants of 7
, 1
, and 10
, which is {3, 7, 8, 11, 1, 2, 4, 12, 5, 6, 9}
, or everything except 10
.可以看到
shallowest([7, 1, 10])
首先找到了7
, 1
, 10
的所有后代,即{3, 7, 8, 11, 1, 2, 4, 12, 5, 6, 9}
,或除10
之外的所有内容。 So when we filter those out of [7, 1, 10]
we are left with just 10
.因此,当我们从
[7, 1, 10]
中过滤掉那些时,我们只剩下10
了。 Similarly, shallowest([1, 2])
and shallowest([1, 4])
produce sets of descendants that don't overlap at all with the input, so the output is identical to the input.类似地,
shallowest([1, 2])
和shallowest([1, 4])
产生与输入完全不重叠的后代集,因此 output 与输入相同。 And with shallowest([2, 3, 1])
, the list of descendants contains 3
but not 2
or 1
, so the output is [2, 1]
.并且使用
shallowest([2, 3, 1])
,后代列表包含3
但不包含2
或1
,因此 output 是[2, 1]
。
This is my 2nd attempt, thanks to jcalz for pointing out the error and his solution is neater than mine.这是我的第二次尝试,感谢 jcalz 指出错误,他的解决方案比我的更整洁。
The function buildArray builds an array of objects in to the variable keyArray, the key is the element in the array to be searched and another array that's the path to that element (so key 7 will have a path of [10, 1, 7]). function buildArray 在变量 keyArray 中构建了一个对象数组,键是要搜索的数组中的元素,另一个数组是该元素的路径(因此键 7 的路径为 [10, 1, 7] )。
We then filter keyArray to remove any elements that have a parent in the original search array.然后我们过滤 keyArray 以删除在原始搜索数组中具有父元素的任何元素。
Anyway, reading jcalz's solution, I've learnt about maps so my time's not been entirely wasted.无论如何,阅读 jcalz 的解决方案,我已经了解了地图,所以我的时间并没有完全浪费。 Hope this helps in some way though.
希望这在某种程度上有所帮助。
console.log(search2([7, 1, 10], obj)); //returns [10]
console.log(search2([1,2], obj)); //returns [1,2]
console.log(search2([2,3,1], obj)); //returns [1,2]
console.log(search2([1,4], obj)); //returns [1,4]
function search2(search, obj) {
keyArray=[];
buildArray(obj);
return keyArray.filter((element)=> !element.path.some(e => search.includes(e))).map((e)=> e.key);
function buildArray(obj, path=[]) {
obj.forEach((element) =>{
if(search.includes(element.key)) {
keyArray.push({"key":element.key,"path":path});
}
buildArray(element.children,[...path,element.key]);
});
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.