Фильтровать массив объектов по общим свойствам - PullRequest
1 голос
/ 20 февраля 2020

Возможно ли каким-то образом отфильтровать, скажем, такой массив массивов объектов:

[[{id: 1}, {id: 2}, {id: 3}], [{id:6}, {id: 2}], [{id: 2}, {id: 1}, {id: 9}, {id: 3}]]

Чтобы получить массив объектов, у которых все массивы имеют одинаковое свойство (id), поэтому в данном случае это вывод будет:

[{id: 2}] // becasue this id is the same in all three subarrays

Я только пробовал пересечение с помощью loada sh, но, похоже, он работает совсем иначе: /

Ответы [ 5 ]

5 голосов
/ 20 февраля 2020

Я бы взял один массив (достаточно взять один, потому что если свойства там нет, оно уже не распространено), в этом примере я беру первый, но, вероятно, более эффективным будет выбор самого короткого.

перебирает массив и проверяет, является ли он общим для всех других массивов.

const arr = [[{id: 1}, {id: 2}, {id: 3}], [{id:6}, {id: 2}], [{id: 2}, {id: 1}, {id: 9}, {id: 3}]];

let firstArray = arr.shift();

const result = firstArray.reduce((common, item)=>{
  if (arr.every(inner => inner.some(_item => _item.id === item.id))) {
    common.push(item);
  }
  
  return common;
},[])

console.log(result);
2 голосов
/ 20 февраля 2020

Использование Рамда :

const input = [[{id: 1}, {id: 2}, {id: 3}], [{id:6}, {id: 2}], [{id: 2}, {id: 1}, {id: 9}, {id: 3}]];
R.intersection(...input);
1 голос
/ 20 февраля 2020

Мой подход аналогичен подходу наортора, но с попыткой быть более обобщенным c.

const intersection = (pred) => (as, bs) =>
  as .filter (a => bs .some (b => pred (a, b)))

const intersectionAll = (pred) => (xs) => 
  xs.length ? xs .reduce (intersection (pred)) : []

const input = [[{id: 1}, {id: 2}, {id: 3}], [{id:6}, {id: 2}], [{id: 2}, {id: 1}, {id: 9}, {id: 3}]]

const eqIds = (a, b) => a .id == b .id 

console .log (
  intersectionAll (eqIds) (input)
)
.as-console-wrapper {min-height: 100% !important}

Эта версия требует, чтобы вы сказали, как вы идентифицируете два равных значения. (Мы проверим, имеют ли они одинаковый идентификатор, но разрешена любая двоичная функция предиката.) Эта функция передается в intersection, которая возвращает функцию, которая принимает два массива и находит все общие элементы между этими двумя. intersectionAll оборачивает это поведение, складывая intersection по массиву массивов.

Эта разбивка полезна, поскольку intersection также является полезной функцией. А абстракция проверки идентификатора в функцию, которую вы должны предоставить, означает, что эти функции гораздо более обобщенные c.

1 голос
/ 20 февраля 2020
 var arr = [
   [{id: 1}, {id: 2}, {id: 3}], 
   [{id:6}, {id: 2}], 
   [{id: 2}, {id: 1}, {id: 9}, {id: 3}]
 ]
 var obj = {};
 var arrLength = arr.length;

 arr.forEach((val,index) => {
  val.forEach((item) =>{
    if(index == 0){
        if(!obj.hasOwnProperty(item.id)){
            obj[item.id] = 1;
        }
    }else{
        if(obj.hasOwnProperty(item.id)){
            obj[item.id] = obj[item.id] + 1;
        }else{
           return;
        }
      }
   });
});

var output = [];

for (const property in obj) {
 if(obj[property] == arrLength){
   output.push({
      id: property
   })
 }
}

console.log(output);
1 голос
/ 20 февраля 2020

Вы можете использовать массивы reduce, forEach, findIndex и sort, чтобы получить наиболее распространенный объект. Вначале внутри обратного вызова Reduce используйте forEach, чтобы выполнить итерацию каждого дочернего массива, а затем используйте findIndex, чтобы найти, существует ли в массиве аккумуляторов объект с таким же идентификатором. Если он не существует, создайте новый объект с ключом id & occurrence. Если оно существует, тогда увеличьте значение вхождения. Это даст наиболее распространенный id, даже если id отсутствует в нескольких дочерних массивах

let data = [
 [{id: 1}, {id: 2}, { id: 3}],
 [{id: 6}, {id: 2}],
 [{id: 2}, {id: 1}, {id: 9}, { id: 3}]
];
let obj = data.reduce((acc, curr) => {
  curr.forEach((item) => {
    let getInd = acc.findIndex((elem) => {
      return elem.id === item.id
    });
    if (getInd === -1) {
      acc.push({
        id: item.id,
        occurence: 1
      })
    } else {
      acc[getInd].occurence += 1;
    }

  })

  return acc;
}, []).sort((a, b) => {
  return b.occurence - a.occurence;
});

console.log(obj[0])
...