使用嵌套值的filter数组给我未定义

时间:2018-01-17 15:53:57

标签: javascript

如何使用嵌套数组中的值过滤顶级数组?

我的代码如下,fiddle

const selectedId = 62;
const filteredEvents = {};
const events = {
  "2018-01-31": {
    dots: [{
      key: "test",
      color: "red",
      categories: [{
        name: "cat 1",
        id: 59
      }, {
        name: "cat 2",
        id: 61
      }, {
        name: "cat 3",
        id: 62
      }]
    }, {
      key: "test again",
      color: "blue",
      categories: [{
        name: "cat 1",
        id: 59
      }, {
        name: "cat 2",
        id: 61
      }]
    }]
  },
  "2018-02-02": {
    dots: [{
      key: "test 1",
      color: "blue",
      categories: [{
        name: "cat 1",
        id: 59
      }]
    }]
  },
  "2018-02-04": {
    dots: [{
      key: "test 2",
      color: "pink",
      categories: [{
        name: "cat 1",
        id: 59
      }]
    }, {
      key: "test 2",
      color: "pink",
      categories: [{
        name: "cat 1",
        id: 59
      }]
    }]
  }
};

使用此过滤器:

   const results = Object.values(events)
                .filter(({ dots: [event] }) => {
                    event.categories.find(
                        category => category.id === selectedId
                    );
                })
                .pop();

// console.log(results) undefined

我只想在过滤后的对象中使用此属性,因为它的类别ID为62:

const events = {
  "2018-01-31": {
    dots: [{
      key: "test",
      color: "red",
      categories: [{
        name: "cat 1",
        id: 59
      }, {
        name: "cat 2",
        id: 61
      }, {
        name: "cat 3",
        id: 62
      }]
    }]
  }

2 个答案:

答案 0 :(得分:1)

您对该过滤器略有疏忽。它是一个箭头函数,它需要以这种形式显式返回:

filter(({ dots: [event] }) => {
    // add "return" here
    return event.categories.find(category => category.id === selectedId);
})

由于你在该区块中没有做任何其他事情,你可以省略括号并返回:

filter(({ dots: [event] }) => event.categories.find(category => category.id === selectedId))

否则,你的过滤器函数总是返回undefined,这意味着filter会把所有东西都拿出来,所以你的pop()什么都没有。

答案 1 :(得分:1)

正如我的评论中所述,您并未从过滤器回调中返回任何内容。

此外,您的解构分配是明确捕获dots数组中的第一个对象而不是所有这些对象。自从查看上一个问题后,您想要搜索所有类别,您需要引用整个数组以获取dots中所有对象的所有类别。



const events = {"2018-01-31":{"dots":[{"key":"test","color":"red","categories":[{"name":"cat 1","id":59},{"name":"cat 2","id":61},{"name":"cat 3","id":62}]},{"key":"test again","color":"blue","categories":[{"name":"cat 1","id":59},{"name":"cat 2","id":61}]}]},"2018-02-02":{"dots":[{"key":"test 1","color":"blue","categories":[{"name":"cat 1","id":59}]}]},"2018-02-04":{"dots":[{"key":"test 2","color":"pink","categories":[{"name":"cat 1","id":59}]},{"key":"test 2","color":"pink","categories":[{"name":"cat 1","id":59}]}]}};

const target = 62;

const results = Object.entries(events)
  .filter(([_, o]) => o.dots.some(oo => oo.categories.some(c => c.id === target)))
  .reduce((res, [k,o]) => ({...res, [k]:o}), {});

console.log(results);




我最后删除了.pop(),因为如果找到多个,那么这将为您提供 last 匹配。不知道为什么会那样。如果你想要所有的比赛,那绝对不应该在那里。如果您只想要一个,我会使用.find()代替.filter()。如果你想要最后一场比赛,我仍然会使用.find(),但会先.reverse()数组。

我还在嵌套数组上使用.some()而不是.find(),因为它提供了更合适的布尔结果,而不是抓取实际上不需要的嵌套对象。它在这里没有什么不同,但我认为它的形式更好。