如何在嵌套数组中找到符合特定条件的第一项,并在找到后停止?
在一维数组中,这就是 Array.find 函数的用途,但是对于二维数组,甚至更整洁的 n 维数组,您将如何执行此操作?
此外,我正在尝试使用 es6 和数组函数(例如 find、map、reduce 等)提出一个简洁的解决方案,而不是使用更传统的循环和变量来维护状态(参见下面的一个这样的老式解决方案).
数据可能看起来像这样
const data = [
{arr: [{val:6,name:'aaa'},{val:4,name:'bbb'},{val:8,name:'ccc'}]},
{arr: [{val:3,name:'mmm'},{val:5,name:'nnn'},{val:9,name:'ppp'},{val:5,name:'ooo'}]}
]
我希望我能做一些类似于 array.find(及其谓词/测试函数)的事情,但我需要更深入地查找例如 val=5 的第一个项目。对于上面的数据,我希望得到名称为“nnn”(不是“ooo”)的项目,并在找到第一个项目后结束流程。与 Array.find 类似,我想避免在找到匹配项后处理其余数据。
一个无聊的旧方法是这样的,有一个循环,但那是......无聊,而且不像可爱的数组函数那样整洁:)
let found
// loop through all data entries in the outer array
for (const d of data) {
// attempt to find a matching item in the inner array.
// using array.find means we stop at the first match, yay!
const theItem = d.arr.find(item => {
return myPredicate(item)
})
// we also need to break out of the loop. ugh!
if (theItem) {
found = theItem
break
}
}
// return what we found (may be undefined)
return found
现在,我意识到我可以用 find() 和 some() 做一些事情,比如说,类似于这里的答案 ES6 - Finding data in nested arrays ,但问题是在外部数组上使用 find 意味着我们取回外部数据数组的第一项,而我想要内部 arr 数组中的一项。
const outer = data.find(d => {
return d.arr.some(item => {
return myPredicate(item)
})
})
然后我将不得不再次处理外部以在 outer.arr 中找到该项目,例如
outer.arr.find(item => myPredicate(item))
这不太适合我,因为对 some(...) 的调用已经完成并找到了匹配的内部项!
我认为这会很简单,也许是,但出于某种原因,我陷入了这个小挑战。
我还查看了不错的遍历库 ( https://www.npmjs.com/package/traverse ),但同样,这似乎更像是遍历整棵树,而不是在找到特定节点后停止并返回。
有人愿意挑战吗? ;)
最佳答案
最简单(虽然有点难看)的解决方案是在找到匹配的 item
时将其分配给外部变量:
let foundNested;
data.some(subarr => (
subarr.some((item) => {
if (myPredicate(item)) {
foundNested = item;
return true;
}
});
});
您可以使用 .reduce
来避免分配给外部变量:
const myPredicate = ({ val }) => val === 5;
const data = [
{arr: [{val:6,name:'aaa'},{val:4,name:'bbb'},{val:8,name:'ccc'}]},
{arr: [{val:3,name:'mmm'},{val:5,name:'nnn'},{val:9,name:'ppp'},{val:5,name:'ooo'}]}
];
const found = data.reduce((a, { arr }) => (
a ||
arr.find(myPredicate)
), null);
console.log(found);
问题是,reduce
不会短路——无论如何它都会完全遍历外部数组。对于真正的短路,我想我更喜欢使用 for..of
循环:
const data = [
{arr: [{val:6,name:'aaa'},{val:4,name:'bbb'},{val:8,name:'ccc'}]},
{arr: [{val:3,name:'mmm'},{val:5,name:'nnn'},{val:9,name:'ppp'},{val:5,name:'ooo'}]}
];
function findNested(outerArr, myPredicate) {
for (const { arr } of outerArr) {
for (const item of arr) {
if (myPredicate(item)) {
return item;
}
}
}
}
const myPredicate = ({ val }) => val === 5;
console.log(findNested(data, myPredicate));
关于javascript - 使用 map reduce 等,你如何在嵌套数组中找到符合特定条件的第一个项目,并在找到后停止?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54470142/