ES6 - 在嵌套数组中查找数据

Tob*_*oby 14 javascript arrays ecmascript-6

在ES6中使用find或者filter我很乐意迭代使用值来查找数组中的元素.

但是,我试图根据嵌套数组中的值从父数组中获取值.

例如,在此数据结构中:

products: [
  {
    id: 01,
    items: [
      {
        id: 01,
        name: 'apple'
      },
      {
        id: 02,
        name: 'banana'
      },
      {
        id: 03,
        name: 'orange'
      }
    ]
  },
  {
    id: 02,
    items: [
      {
        id: 01,
        name: 'carrot'
      },
      {
        id: 02,
        name: 'lettuce'
      },
      {
        id: 03,
        name: 'peas'
      }
    ]
  },
  {
    id: 03,
    items: [
      {
        id: 01,
        name: 'eggs'
      },
      {
        id: 02,
        name: 'bread'
      },
      {
        id: 03,
        name: 'milk'
      }
    ]
  }
]
Run Code Online (Sandbox Code Playgroud)

如果我知道对象nameid对象milk,有没有办法找出它嵌套在其中的元素的id?

目前我有这个:

products.find((product) => {
  product.find((prod) => {
    return prod.name === 'milk';
  });
});
Run Code Online (Sandbox Code Playgroud)

其中只返回包含的对象milk.

Ber*_*rgi 37

你必须从外部的回调中返回一些东西find.实际上,对于内部迭代,您不应该使用find而是some返回一个布尔值,表示在arrray中是否存在与条件匹配的元素:

products.find((product) => {
  return product.items.some((item) => {
//^^^^^^
    return item.name === 'milk';
  });
});
Run Code Online (Sandbox Code Playgroud)

或简而言之:

products.find(product => product.items.some(item => item.name === 'milk'));
Run Code Online (Sandbox Code Playgroud)

然后检查是否find找到了某些东西(不是null!)并得到它.id,结果应该是03.或者,您可以filter将包含牛奶的产品作为项目,然后将所有结果映射到其ID:

products.filter(product =>
  product.items.some(item => item.name === 'milk');
).map(product =>
  product.id
) // [03]
Run Code Online (Sandbox Code Playgroud)


ari*_*iel 18

我知道你提到了 ES6,但在这种情况下(如果你想返回内部对象)我相信使用for/of而不是map/ reduce/更好find

for (let p of products) {
  for (let i of p.items) {
    if (i.name === 'milk') return i;
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 这似乎是最干净的解决方案(无论是可读性还是性能)。这是函数式编程不适合解决该问题的少数情况之一。 (2认同)

小智 12

另一种方法:

products
  .map((category) => category.items)
  .flat()
  .find((product) => product.name === 'milk');
Run Code Online (Sandbox Code Playgroud)


Gus*_*lli 8

更新

正如 Ricardo Marimon 评论的那样,reduce 不会中断,因此它会继续搜索数组,因此考虑到这一点,因为我不喜欢使用 for 循环命令式编程方式,所以可以通过改变所使用的数组来提前中断reduce ,但这也很糟糕,因此也可以制作副本并改变副本。

// slice creates a copy of products
return products.slice(0).reduce((prev, product, i, arr) => {
    console.log(i);
    const findItem = prev || product.items.find(item => item.name === 'milk');
    if (typeof findItem !== 'undefined') arr.splice(1); // ejects early
    return findItem;
}, undefined);
Run Code Online (Sandbox Code Playgroud)

const products = [
  {id: 1, items: [
    {id: 1, name: 'apple'},
    {id: 2, name: 'banana'},
    {id: 3, name: 'orange'}
  ]},
  {id: 2, items: [
    {id: 1, name: 'carrot'},
    {id: 2, name: 'lettuce'},
    {id: 3, name: 'milk'}
  ]},
  {id: 3, items: [
    {id: 1, name: 'eggs'},
    {id: 2, name: 'bread'},
    {id: 3, name: 'peas'}
  ]}
];

const findItem = products.slice(0).reduce((prev, product, i, arr) => {
    console.log(i);
    const findItem = prev || product.items.find(item => item.name === 'milk');
    if (typeof findItem !== 'undefined') arr.splice(1); // ejects early
    return findItem;
}, undefined);

console.log(findItem);
Run Code Online (Sandbox Code Playgroud)

老的

接受的答案并不适合我,因为我想要内部查找的结果,使用两者总是给我外部过滤/查找的结果,并且我必须使用结果数组再次查找该值。

因此,我使用了带有短路的减少来获得内部结果。

// undefined as the initial value is necessary, otherwise it gets the first value of the array instead.

return products.reduce((prev, product) => prev || product.items.find(item => item.name === 'milk'), undefined);
Run Code Online (Sandbox Code Playgroud)

const products = [
  {id: 1, items: [
    {id: 1, name: 'apple'},
    {id: 2, name: 'banana'},
    {id: 3, name: 'orange'}
  ]},
  {id: 2, items: [
    {id: 1, name: 'carrot'},
    {id: 2, name: 'lettuce'},
    {id: 3, name: 'peas'}
  ]},
  {id: 3, items: [
    {id: 1, name: 'eggs'},
    {id: 2, name: 'bread'},
    {id: 3, name: 'milk'}
  ]}
];

console.log(products.reduce((prev, product) => prev || product.items.find(item => item.name === 'milk'), undefined));
Run Code Online (Sandbox Code Playgroud)

  • 请注意,即使找到该项目,这种方式也会继续搜索该项目。reduce 函数不能被破坏。@ariel 的解决方案在发现时确实中断了。 (2认同)