【问题标题】:How to filter on properties of children object and return the parent with children that passes the filter in Javascript?如何过滤子对象的属性并返回带有通过 Javascript 过滤器的子对象的父对象?
【发布时间】:2019-04-25 03:48:32
【问题描述】:

我想过滤子对象的属性并返回具有通过过滤器的子对象的父母。

我尝试使用 Array.filter、Array.some 和 Object.values 的组合,但是一旦我使用了 Object.values,我想不出一种方法来取回密钥

var data = {
    parent1: {
        child1: {
            source: true
        },
        child2: {
            source: true
        }
    },
    parent2: {
        child3: {
            source: true
        },
        child4: {
            source: false
        }
    },
    parent3: {
        child5: {
                source: false
        }
    }
}

我希望结果是:

var afterFilter = {
    parent1: {
        child1: {
            source: true
        },
        child2: {
            source: true
        }
    },
    parent2: {
        child3: {
            source: true
        }
    }
}

【问题讨论】:

  • 你的输入对象和输出对象是一样的。我说的对吗?
  • 为什么它们是一样的?输出排除了来源为假的孩子,也排除了没有任何合格孩子的父母。所以他们是不同的。但是结构明智,是的,它们是相同的,我想保持结构。

标签: javascript ecmascript-6


【解决方案1】:

如果您想要一个具有可重用功能的解决方案,我建议您查看此实现。

const data = {parent1:{child1:{source:true},child2:{source:true}},parent2:{child3:{source:true},child4:{source:false}},parent3:{child5:{source:false}}}

function objectMapReduce (object, map, filter) {
  // iterate key-value pairs of object
  return Object.entries(object).reduce(
    (accumulator, [key, value]) => {
      // map each value in object
      const result = map(value, key, object)
      // filter each mapped value
      return filter(result, key, object)
        ? Object.assign(accumulator, { [key]: result })
        : accumulator
    },
    // initial value of accumulator
    {}
  )
}

const afterFilter = objectMapReduce(
  data, // map-reduce each parent in data
  parent => objectMapReduce(
    parent, // map-reduce each child in parent
    ({ source}) => ({ source }), // copy each child
    ({ source }) => source // keep child if source is true
  ),
  parent => Object.keys(parent).length > 0 // keep non-empty parent
)

console.log(afterFilter)

【讨论】:

    【解决方案2】:

    除了使用数组方法,你也可以尝试一个简单的for...of循环:

    var data = {
      parent1: {
        child1: {
          source: true
        },
        child2: {
          source: true
        }
      },
      parent2: {
        child3: {
          source: true
        },
        child4: {
          source: false
        }
      },
      parent3: {
        child5: {
          source: false
        }
      }
    }
    
    var afterFilter = {};
    
    for (const [key, value] of Object.entries(data)){
    
      for (const [k, v] of Object.entries(value)){
    
        const { source } = v;
    
        if (source !== true)
          continue;
    
        // If `afterFilter[key]` does not exist, init with {}
        afterFilter[key] = afterFilter[key] || {};
        afterFilter[key][k] = { source };
    
      }
    
    }
    
    console.log(afterFilter)

    【讨论】:

      【解决方案3】:

      使用 Array.reduceObject.entries 尝试此操作,对于每个父项 /em> 遍历父对象的子对象过滤它基于source

      如果 parent 的当前 child 的 source 为 true 则将其添加到 reduce 的累加器 acc else 忽略它:

      const data = {parent1:{child1:{source:true},child2:{source:true}},parent2:{child3:{source:true},child4:{source:false}},parent3:{child5:{source:false}}};
      
      const res = Object.entries(data).reduce((acc, [key, value]) =>{
        for(child in value){ //value is the child-object of the parent, iterating throgh all the key of the child and checking if the source is true for this key of the child
          if(value[child].source){
            acc[key] = {...acc[key], [child] : value[child]}; //using spread operator to preserve previous values
          }
        }
        return acc;
      }, {});
      console.log(res);

      【讨论】:

        【解决方案4】:

        如果你发现谁的孩子是真的并返回那个父母,也许这对你来说是正确的答案

        const data = [
        { name: 'parent1', parent : { child: { source : true } } },
        { name: 'parent2', parent : { child: { source : true } } },
        { name: 'parent3', parent : { child: { source : false } } }
        

        ];

        const newData = data.filter((e)=> e.parent.child.source === true);
        console.log(newData);
        

        【讨论】:

          【解决方案5】:

          这是我的解决方案。试试这个

          var data = {
              parent1: {
                  child1: {
                      source: true
                  },
                  child2: {
                      source: true
                  }
              },
              parent2: {
                  child3: {
                      source: true
                  },
                  child4: {
                      source: false
                  }
              },
              parent3: {
                  child5: {
                          source: false
                  }
              }
          }
          
          var afterFilter = {}
          
          
          for(var key in data){
          
              for(var childkey in data[key]){
          
                  if(data[key][childkey].source){
          
                      if(afterFilter[key])
                          afterFilter[key][childkey] = data[key][childkey]
                      else
                          afterFilter[key] = {[childkey]: data[key][childkey]}
          
                  }
                      
              }
          
          }
          
          console.log(afterFilter);

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2022-01-21
            • 1970-01-01
            • 1970-01-01
            • 2019-05-29
            • 1970-01-01
            • 2015-06-21
            • 1970-01-01
            • 2018-10-11
            相关资源
            最近更新 更多