Как отфильтровать по свойствам дочернего объекта и вернуть родителя с дочерними объектами, который проходит фильтр в Javascript? - PullRequest
3 голосов
/ 25 апреля 2019

Я хочу отфильтровать по свойству дочерний объект и вернуть родителей с детьми, которые проходят фильтр.

Я пытался с комбинацией 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
        }
    }
}

Ответы [ 5 ]

0 голосов
/ 25 апреля 2019

Если вам нужно решение с функцией многократного использования, я предлагаю взглянуть на эту реализацию.

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)
0 голосов
/ 25 апреля 2019

Это моё решение.Попробуйте это

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);
0 голосов
/ 25 апреля 2019

Вместо использования методов Array, вы также можете попробовать простой цикл 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)
0 голосов
/ 25 апреля 2019

Если вы найдете, чьи дети истинны, и вернете этого родителя, возможно, это правильный ответ для вас

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);
0 голосов
/ 25 апреля 2019

Попробуйте, используя Array.reduce и Object.entries,для каждого родителя запись перебирает дочерние элементы родительского объекта, фильтрует его на основе source.

Если текущий дочерний элемент родителя имеет источник как true, то добавьте егок аккумулятору acc уменьшения, игнорируйте его:

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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...