简体   繁体   中英

Filter array of objects by key and value contained in another object

There is a way to filter (or query) an array structured like this:

[   {
            'xml:id': 'Name1',
            sex: {
                '$t': 'M'
            },
            occupation: {
                n: 1,
                '$t': 'bank'
            }
        },
        {
            'xml:id': 'Name2',
            sex: {
                '$t': 'M'
            },
            occupation: {
                n: 1,
                '$t': 'writer'
            }
        }, {
            'xml:id': 'Name3',
            sex: {
                '$t': 'F'
            },
            occupation: {
                n: 1,
                '$t': 'bank'
            }
        }, {
            'xml:id': 'Name4',
            sex: {
                '$t': 'M'
            },
            occupation: {
                n: 1,
                '$t': 'writer'
            },
        }, {
            'xml:id': 'Name5',
            sex: {
                '$t': 'M'
            },
            occupation: {
                n: 1,
                '$t': 'writer'
            }
        }
    ]

whit a query of this type:

const pers_query: Query = {
  type: 'person',
  args: [
    {
      key: 'occupation',
      value: 'bank',
    },
    {
      key: 'sex',
      value: 'f',
    },
  ],
};

What I want is to filter the data with multiple keys and values, in this specific case I want to filter the data for all the occurrences of object that contains the key sex with value f AND the key occupation with value bank

the result should be something like this:

[
   {
        'xml:id': 'Name3',
        sex: {
            '$t': 'F'
        },
        occupation: {
            n: 1,
            '$t': 'bank'
        }
    }
]

You can use a combination of Array.prototype.filter() and Array.prototype.each

 const input = [{ 'xml:id': 'Name1', sex: { '$t': 'M' }, occupation: { n: 1, '$t': 'bank' } }, { 'xml:id': 'Name2', sex: { '$t': 'M' }, occupation: { n: 1, '$t': 'writer' } }, { 'xml:id': 'Name3', sex: { '$t': 'F' }, occupation: { n: 1, '$t': 'bank' } }, { 'xml:id': 'Name4', sex: { '$t': 'M' }, occupation: { n: 1, '$t': 'writer' }, }, { 'xml:id': 'Name5', sex: { '$t': 'M' }, occupation: { n: 1, '$t': 'writer' } }] const pers_query = { type: 'person', args: [{ key: 'occupation', value: 'bank', }, { key: 'sex', value: 'f', }, ], }; const output = input.filter(person => { return pers_query.args.every(condition => { return person[condition.key]['$t'].toLowerCase() === condition.value.toLowerCase(); }); }); console.log(output);

function filterData(data,query,caseSensitive=false) {
    let filteredData = data;
    // no use for type since it's  not in data
    query.args.forEach(arg => filteredData = filteredData.filter(item => caseSensitive ? item[arg.key]['$t'] === arg.value : item[arg.key]['$t'].toLowerCase() === arg.value.toLowerCase())); // you can use .lowe

    return filteredData;
}

This is one way to do it, note that we assign filteredData with data at beginning since where applying filter and that won't cause any change to the original array.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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