Примените фильтр к многоуровневому объекту на основе другого объекта

#javascript #filter #functional-programming

Вопрос:

У меня есть массив с многоуровневыми объектами, такими как:

 list= [ {   type: { name: 'dog', size:'medium'},  entity: { name: 'Tobby', age: '7'},  },  {   type: { name: 'cat', size:'small'},  entity: { name: 'Garfield', age: '7'},  }  ]  

И у меня есть определенный фильтр, такой как:

 filter={  type: { name:'dog'}}  

Мне нужно определить функцию, которую я могу вызвать

 let filtered = list.thisMagicFilter(filter)  

это будет соответствующим образом фильтроваться в моем списке (в данном примере возвращается только первый элемент.

Логически, если фильтр есть {entity:{age:'7'}} , то должны быть возвращены оба результата.

Я сломал голову , пытаясь сделать это в функциональном программировании с помощью a list.filter() , но это просто слишком сложно для меня: я борюсь с тем фактом, что это проверка на 2 уровне.

Могу ли я получить некоторые подсказки о том, как решить эту проблему?

Заранее благодарю вас!

Ответ №1:

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

 const  list = [{ type: { name: 'dog', size: 'medium' }, entity: { name: 'Tobby', age: '7' } }, { type: { name: 'cat', size: 'small' }, entity: { name: 'Garfield', age: '7' } }],  filter = { type: { name: 'dog' } },  filterBy = f =gt; o =gt; Object  .entries(f)  .every(([k, v]) =gt; typeof v === 'object'  ? filterBy(v)(o[k])  : o[k] === v  ),  result = list.filter(filterBy(filter));  console.log(result); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

Ответ №2:

Попробуй это:

 const _matchesFilter = (e, conditions = []) =gt;  conditions.every(([prop, condition]) =gt; {  const subConditions = Object.entries(condition);  return subConditions.every(([ subProp, subCondition ]) =gt;  e[prop]?.[subProp] === subCondition  );  });  const thisMagicFilter = (list = [], filter = {}) =gt; {  const conditions = Object.entries(filter);  return list.filter(e =gt; _matchesFilter(e, conditions)); }  const list= [   { type: { name: 'dog', size:'medium'}, entity: { name: 'Tobby', age: '7'} },  { type: { name: 'cat', size:'small'}, entity: { name: 'Garfield', age: '7'} } ]; console.log( thisMagicFilter(list) ); console.log( thisMagicFilter(list, { type: { name: 'dog'} }) ); console.log( thisMagicFilter(list, { entity: { age: '7'} }) ); console.log( thisMagicFilter(list, { entity: { name: 'Garfield', age: '7'} }) ); console.log( thisMagicFilter(list, { type: { size: 'medium' }, entity: { age: '7'} }) );