简体   繁体   中英

How to filter on properties of children object and return the parent with children that passes the filter in Javascript?

I want to filter on the property of children object and return parents with children that passes the filter.

I tried with combination of Array.filter, Array.some, and Object.values, but I can't think of a way to get the key back once Ive used Object.values

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

I want the outcome to be:

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

Try this using Array.reduce and Object.entries , for each parent entry iterate through the children of the parent object filter it based on the source .

If the current child of the parent has the source as true then add it to the accumulator acc of the reduce else ignore it:

 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); 

Instead of using Array methods, you can also try a simple for...of loop:

 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) 

If you find to find whose children is true and return that parent, maybe this is correct answer for you

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);

This is my solution. Try this

 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); 

If you want a solution with a reuseable function, I suggest looking at this implementation.

 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) 

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