【问题标题】:Javascript filter arrays within an objectJavascript过滤对象内的数组
【发布时间】:2020-10-21 11:39:33
【问题描述】:

假设我有一个具有结构的对象

data = {
    a : [{values: {key1: 5, key2: "abc"}}, {values: {key1: 3, key2: "abc"}}, {values: {key1: 4, key2: "cde"}}],
    b : [{values: {key1: 3, key2: "ffe"}}, {values: {key1: 11, key2: "gga"}}, {values: {key1: 7, key2: "abc"}}]
}

我想提取 key2 == "abc" 所在的元素。

预期输出:

data = {
    a : [{values: {key1: 5, key2: "abc"}}, {values: {key1: 3, key2: "abc"}}],
    b : [{values: {key1: 7, key2: "abc"}}]
}

我尝试关注类似的examples,但未能实现我想要的。

【问题讨论】:

    标签: javascript object filter reduce


    【解决方案1】:

    使用Object.entries()data 的所有键/值对提取为一个数组,map 在每对上,然后在每个值上使用filter 以提取您想要的。

    然后您可以使用 Object.fromEntries() 重新加入它

    const data = {
        a : [{values: {key1: 5, key2: "abc"}}, {values: {key1: 3, key2: "abc"}}, {values: {key1: 4, key2: "cde"}}],
        b : [{values: {key1: 3, key2: "ffe"}}, {values: {key1: 11, key2: "gga"}}, {values: {key1: 7, key2: "abc"}}]
    }
    
    const findKey = 'key2'
    const findValue = 'abc'
    
    const newData = Object.fromEntries(Object.entries(data).map(([ key, val ]) =>
      [ key, val.filter(({ values }) => values?.[findKey] === findValue) ]))
      
    console.log(newData)

    如果你还没有看到Optional Chaining,这个...

    values?.[findKey] === findValue
    

    等价于

    !!values && values[findKey] === findValue
    

    【讨论】:

    • 我的大脑很痛,试图跟随那里发生的所有解构。
    • 虽然这行得通,但这里有太多的解构,你可能会失去流程
    • @ManosKounelakis 这里只有两个解构,一个数组 ([ key, val ]) 和一个对象 ({ value })。不确定你认为什么太多?
    • 你真的需要可选链吗?我想如果您尝试访问不存在的第一层的属性,它会返回未定义?
    • @Ifaruki 以防任何数组条目没有 values 属性。如果他们这样做了,values 将是 undefinedvalues[findKey] 会抛出一个错误
    【解决方案2】:

    简单的 for of 循环遍历键和 filters 数组并直接重新分配属性。
    直接改变数据。

    使用filterdestructures key2 对其进行过滤。

    const data = {
        a : [{values: {key1: 5, key2: "abc"}}, {values: {key1: 3, key2: "abc"}}, {values: {key1: 4, key2: "cde"}}],
        b : [{values: {key1: 3, key2: "ffe"}}, {values: {key1: 11, key2: "gga"}}, {values: {key1: 7, key2: "abc"}}]
    }
    
    for(const k of Object.keys(data))
      data[k] = data[k].filter(({values: {key2}})=>key2==='abc')
      
    console.log(data)

    添加了对 .length 的检查以修剪具有空数组的键,
    并为 key2 设置默认值,因此 values 属性是可选的:

    const data = {
        a : [{values: {key1: 5, key2: "abc"}}, {values: {key1: 3, key2: "abc"}}, {values: {key1: 4, key2: "cde"}}],
        b : [{values: {key1: 3, key2: "ffe"}}, {values: {key1: 11, key2: "gga"}}, {values: {key1: 7, key2: "abc"}}]
    }
    
    for(const k of Object.keys(data))
      (data[k] = data[k].filter(({values:{key2}={}})=>key2==='abc'))
        .length || delete data[k]
      
    console.log(data)

    【讨论】:

      【解决方案3】:
      data = {
          a : [{values: {key1: 5, key2: "abc"}}, {values: {key1: 3, key2: "abc"}}, {values: {key1: 4, key2: "cde"}}],
          b : [{values: {key1: 3, key2: "ffe"}}, {values: {key1: 11, key2: "gga"}}, {values: {key1: 7, key2: "abc"}}]
      }
      
      var resp = {}
      for (var key in data){
          var local = [];
          data[key].forEach(element => {
              if(element['values']['key2'] == 'abc'){
                  local.push(element);
              }
          })
          resp[key] = local;
      }
      console.log(resp);
      

      回应

      a : [{values: {key1: 5, key2: "abc"}}, {values: {key1: 3, key2: "abc"}}],
      b : [{values: {key1: 7, key2: "abc"}}]
      

      【讨论】:

        【解决方案4】:

        您可以将对象的属性简化为通过过滤器的属性

        const data = {
            a : [{values: {key1: 5, key2: "abc"}}, {values: {key1: 3, key2: "abc"}}, {values: {key1: 4, key2: "cde"}}],
            b : [{values: {key1: 3, key2: "ffe"}}, {values: {key1: 11, key2: "gga"}}, {values: {key1: 7, key2: "abc"}}]
        };
        
        const results = Object.getOwnPropertyNames(data).reduce((results, key) => {
          const filtered = data[key].filter(item => item.values.key2 === 'abc');
          if (filtered && filtered.length) {
            results[key] = filtered;
          }
          return results;
        }, {});
        
        console.log(results);

        【讨论】:

        • 如果他们想要省略空结果,可能需要与 OP 澄清,但这是一个很好的补充
        【解决方案5】:

        由于您需要迭代对象属性,我建议您使用Object.keys(object) 提取它们,您可以在此处找到:

        https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Objetos_globales/Object/keys

        我建议你这样迭代:

        Object.keys(data).forEach(attribute => {
                data[attribute] = data[attribute].filter(value => value.values.key2 === 'abc');
        })
        
        

        祝你好运。

        【讨论】:

          猜你喜欢
          • 2020-02-21
          • 2012-11-15
          • 1970-01-01
          • 1970-01-01
          • 2022-11-27
          • 1970-01-01
          • 2019-05-29
          • 2021-11-10
          相关资源
          最近更新 更多