通过通用属性过滤对象数组

时间:2020-02-20 15:00:06

标签: javascript arrays data-structures filter javascript-objects

是否可以通过某种方式过滤这样的对象数组数组:

[[{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

我只尝试了从loadash求交,但似乎完全可以通过其他方式工作:/

5 个答案:

答案 0 :(得分:5)

我将采用一个数组(足以容纳一个数组,因为如果该属性不存在,它就已经不常见了),在此示例中,我采用的是第一个数组,但选择最短的数组可能更有效。

遍历数组,并检查每个对象是否与其他所有数组相同。

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

答案 1 :(得分:2)

使用Ramda

const input = [[{id: 1}, {id: 2}, {id: 3}], [{id:6}, {id: 2}], [{id: 2}, {id: 1}, {id: 9}, {id: 3}]];
R.intersection(...input);

答案 2 :(得分:1)

您可以使用数组reduceforEachfindIndexsort来获取最常见的对象。首先在reduce回调内部使用forEach迭代每个子数组,然后使用findIndex查找累加器数组中是否存在具有相同id的对象。如果不存在,请使用键idoccurrence创建一个新对象。如果存在,则增加出现的值。即使少数子数组中不存在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])

答案 3 :(得分:1)

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

答案 4 :(得分:1)

我的方法与naortor相似,但尝试更加通用。

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}

此版本要求您说出如何识别两个相等的值。 (我们将检查它们是否具有相同的id,但允许使用任何二进制谓词函数。)此函数传递给intersection,该函数返回一个接受两个数组并查找这两个数组中所有公共元素的函数。 intersectionAll总结了这一行为,将intersection折叠在一个数组数组上。

此细分非常有用,因为intersection本身也是有用的功能。将id检查抽象为您需要提供的功能意味着这些功能更加通用。