I got a code to remove child/parent elements from a random array that might contain both a child and a parent element, for example:
<html>
<body>
<div id='1'>
<div id='2'>
<div id='3'>
</div>
<div id='4'>
</div>
</div>
</div>
<div id='5'>
<div id='6'>
</div>
</div>
</body>
</html>
arr = document.getElementsByTagName('div')
// arr: [<div#1>,<div#2>, <div#3>, <div#4>, <div#5>, <div#6>]
So from this example how can I extract the children:
// arr: [<div#3>, <div#4><div#6>]
Or extract the parents:
// arr: [<div#1>, <div#5>]
currently I'm using:
function isDescendant(parent, child) {
var node = child.parentNode;
while (node != null) {
if (node == parent) {
return true;
}
node = node.parentNode;
}
return false;
}
function filterArray(arr, parent=true){
newArr = [];
arr.forEach((a)=>{
bool = true
if (parent){
arr.forEach((b)=>{
if (isDescendant(a, b)){
bool = false
};
});
}
else{
arr.forEach((b)=>{
if (isDescendant(b, a)){
bool = false
};
});
}
if(bool){
newArr.push(a)
}
});
return newArr
};
But I'm pretty sure there could be a better solution, more efficient. Any idea for a better solution?
答案 0 :(得分:1)
数组有一个名为filter
的方法,可以让你做到这一点;过滤数组。要查找节点是否是另一个节点的父节点或子节点,您可以使用contains
- 方法(请注意,在检查节点是否包含自身时,这可能会返回true),或者更通用的{{3} } -method。
<div id='1'>
<div id='2'>
<div id='3'>
</div>
<div id='4'>
</div>
</div>
</div>
<div id='5'>
<div id='6'>
</div>
</div>
contains
快速基准测试显示最快的方法(至少在我的机器上)(毫不奇怪,它不必多次搜索数组),然后是compareDocumentPosition
- 版本。最慢的是使用filterArray
,但这仍然比运行npm install --save-dev babel-plugin-transform-class-properties
以获取子数组更快。
答案 1 :(得分:0)
对于儿童可以使用filter()
将集合转换为数组querySelector()
,当元素不是父母时,它不会返回任何内容
对于外部父母,可以使用Array#some()
和node#contains()
作为过滤器()
const arr = Array.from(document.querySelectorAll('div'));
const innerChildren = arr.filter(el => !el.querySelector('*')); // or use same selector as master query
const outerParents = arr.filter(e => !arr.some(el => el !== e && el.contains(e)));
console.log(innerChildren) // div#3, div#4 & div#6
console.log(outerParents) // div#1, div#5
&#13;
<div id='1'>
<div id='2'>
<div id='3'></div>
<div id='4'></div>
</div>
</div>
<div id='5'>
<div id='6'></div>
</div>
&#13;
答案 2 :(得分:0)
试试以下内容。它选择了正确的答案,虽然不是通用的。希望适用于您的情况。应该在场景下的数据循环较少。
const nodes = Array.from(document.body.querySelectorAll("div"));
const children = nodes.filter( node => 0 === node.querySelectorAll('div').length );
const parents = nodes.filter( node => 'DIV' !== node.parentNode.nodeName );
这是JsFiddle: https://jsfiddle.net/3nhzvat9/
和另一个应该表现得更好的解决方案:
const nodes = document.body.querySelectorAll("div");
const children = [];
const parents = [];
nodes.forEach( node => {
if(0 === node.querySelectorAll('div').length) {
children.push(node);
}
if('DIV' !== node.parentNode.nodeName){
parents.push(node);
}
});
第二个JsFiddle:https://jsfiddle.net/3nhzvat9/1/