简体   繁体   English

在嵌套的对象数组中使用过滤器

[英]using filter in a nested array of object

I want to have an array that return certain property base on the checked property. 我想有一个数组,它返回checked属性的某些属性。

const data = [
      {
        "param": "type",
        "id": 6,
        "data": [
          {
            "name": "Collect",
            "filterKey": "collect",
            "checked": false
          },
          {
            "name": "Redeem",
            "filterKey": "redeem",
            "checked": true
          }
        ]
      },
      {
        "param": "country",
        "id": 5,
        "data": [
          {
            "name": "Malaysia",
            "filterKey": "my",
            "checked": true
          },
          {
            "name": "Singapore",
            "filterKey": "sg",
            "checked": false
          }
        ]
      }
    ]

Why my code below doesn't work? 为什么我的代码不起作用? It's a function I use for my check or uncheck event 这是我用于检查或取消选中事件的功能

const checkedKeys = data.map(o => {
        return o.data.filter(o2 => {
          return o2.checked === true
        }).filterKey
    })

I expect to get ['my', 'redeem'] for above case. 对于上述情况['my', 'redeem']我希望得到['my', 'redeem']

Why my code below doesn't work? 为什么我的代码不起作用? It's a function I use for my check or uncheck event 这是我用于检查或取消选中事件的功能

Because filter returns an array and that array won't have filterKey property. 因为filter返回一个数组 ,该数组不具有filterKey属性。

Use reduce , filter and map 使用reducefiltermap

var output = data.reduce( ( a, b ) => //use reduce to accumulate all filtered values
            a.concat( b.data.filter( o2 =>  //filter by checked
                o2.checked ).map( o3 =>   // map to get only the filterKey property
                   o3.filterKey ) ) , []); //[] is the initial value of accumulator

Demo 演示

 var data = [ { "param": "type", "id": 6, "data": [ { "name": "Collect", "filterKey": "collect", "checked": false }, { "name": "Redeem", "filterKey": "redeem", "checked": true } ] }, { "param": "country", "id": 5, "data": [ { "name": "Malaysia", "filterKey": "my", "checked": true }, { "name": "Singapore", "filterKey": "sg", "checked": false } ] } ]; var output = data.reduce( (a,b) => a.concat( b.data.filter( o2 => o2.checked ).map( o3 => o3.filterKey ) ) , []) ; console.log( output ); 

You can try something like this as well. 你也可以试试这样的东西。

Logic 逻辑

  • Create a temporary array. 创建一个临时数组。 ( acc in below example ). acc在下面例子 )。
  • Loop over data and in turn loop over data[i].data 循环data ,然后循环data[i].data
  • Check if checked is true, push filterKey value to acc . 检查checked是否为true,将filterKey值推filterKey acc

ES5 Version: ES5版本:

 var data = [ { "param": "type", "id": 6, "data": [ { "name": "Collect", "filterKey": "collect", "checked": false }, { "name": "Redeem", "filterKey": "redeem", "checked": true } ] }, { "param": "country", "id": 5, "data": [ { "name": "Malaysia", "filterKey": "my", "checked": true }, { "name": "Singapore", "filterKey": "sg", "checked": false } ] } ]; var result = data.reduce(function(acc, obj) { obj.data.forEach(function(curObj) { if (curObj.checked) { acc.push(curObj.filterKey) } }) return acc; }, []) console.log(result); 

ES6 Version: ES6版本:

 var data = [ { "param": "type", "id": 6, "data": [ { "name": "Collect", "filterKey": "collect", "checked": false }, { "name": "Redeem", "filterKey": "redeem", "checked": true } ] }, { "param": "country", "id": 5, "data": [ { "name": "Malaysia", "filterKey": "my", "checked": true }, { "name": "Singapore", "filterKey": "sg", "checked": false } ] } ]; var result = data.reduce((acc, obj) => { obj.data.forEach(({filterKey, checked}) => { checked && acc.push(filterKey) }) return acc; }, []) console.log(result); 

You can achieve this by using simple javascript too which is seemingly easy to understand and will you to edit easily for future changes. 您可以通过使用简单的javascript来实现这一点,这看起来很容易理解,并且您可以轻松编辑以备将来的更改。 Although the complexity based on time and space is same when you use ECMA script or pure javascript. 虽然使用ECMA脚本或纯JavaScript时基于时间和空间的复杂性相同。 Just depends on shorthand codes. 只取决于速记码。

 var data = [ { "param": "type", "id": 6, "data": [ { "name": "Collect", "filterKey": "collect", "checked": false }, { "name": "Redeem", "filterKey": "redeem", "checked": true } ] }, { "param": "country", "id": 5, "data": [ { "name": "Malaysia", "filterKey": "my", "checked": true }, { "name": "Singapore", "filterKey": "sg", "checked": false } ] } ]; var checkedKeys = []; data.forEach((dataItem)=>{ dataItem.data.forEach((innerData)=>{ if(innerData.checked){ checkedKeys.push(innerData.filterKey); } }); }); console.log(checkedKeys) 

A solution with array.protoype.concat , array.protoype.filter , array.protoype.map and spread operator of ES6: 使用array.protoype.concatarray.protoype.filterarray.protoype.map和ES6的spread运算符的解决方案:

 var data = [ { "param": "type", "id": 6, "data": [{"name": "Collect", "filterKey": "collect", "checked": false }, {"name": "Redeem", "filterKey": "redeem", "checked": true }]}, {"param": "country","id": 5,"data": [{"name": "Malaysia","filterKey": "my","checked": true}, {"name": "Singapore","filterKey": "sg","checked": false}]}]; var result = [].concat(...data.map(o => o.data)).filter(d => d.checked).map(d => d.filterKey); console.log(result); 

data.map( // iterate over the top level list
  x => (
    x.data.filter( // select only the checked items from the nested `data` list
      y => y.checked
    ).map( // select only the `filterKey` property of the filtered items
      y => y.filterKey
    )
  )
).reduce( // flatten the end-result [['redeem'],['my']] -> ['redeem', 'my]
  (acc, prev) => acc.concat(prev), []
);

Cleaner way to achieve same thing. 更清洁的方式来实现同样的事情。

 data.map(o => o.data) //gets dataArray .reduce((a, c) => a.concat(c), []) //concats array .filter(o => o.checked) // filters for checked= true .map(o => o.filterKey) //returns filter key 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM