JavaScript:使用Reduce()构造一个比较输入数组的函数交集;仅返回相交元素

时间:2019-06-14 17:25:02

标签: javascript function return reduce

构造一个函数交集,该交集比较输入数组,并返回一个新数组,其中包含在所有输入中找到的元素。

我的解决方案有效,但是非常麻烦:

const intersection = (arrMerged) => {

  let finalArr = []; 
  let flatArray = [].concat(...arrMerged)

  let newArr = []; 
  //console.log(flatArray)

  //let interArray = []; 

  if (arrMerged[2] !== undefined){

    newArr = arrMerged[0].map((elem) => {
      if (arrMerged[1].includes(elem) && arrMerged[2].includes(elem)){
        return elem; 
      }
    })
  }

  else {
    newArr = arrMerged[0].map((elem) => {
      if (arrMerged[1].includes(elem)){
        return elem; 
      }
    })
  }


  newArr.forEach((elem) => {
    if (elem !== undefined){
      finalArr.push(elem)
    }
  })
  return finalArr; 
}

// Uncomment these to check your work!
const arr1 = [5, 10, 15, 20];
const arr2 = [15, 88, 1, 5, 7];
const arr3 = [1, 10, 15, 5, 20];

console.log(intersection([arr1, arr2, arr3])); // should log: [5, 15]

我也想在我的解决方案中使用reduce()。有人可以提供使用reduce()且效率更高的替代代码解决方案吗?

如果您能评论代码的每一行正在做什么以帮助我理解,我将不胜感激。

3 个答案:

答案 0 :(得分:2)

您可以像这样使用reduce

const intersection = (arrays) =>
    arrays.reduce((a, b) =>
        a.filter(c => b.some(d => c === d)) 
    );

filter部分执行两个给定数组ab的交集。 reduce部分通过从输入中获取下一个数组并将其与上一个结果相交来应用此逻辑。

但是,这不是最佳方法。使用大型数组时,请使用Set以获得更好的性能。

const intersection = (arrays) =>
    arrays.reduce((a, b) => {
        const set = new Set(b);
        return a.filter(c => set.has(c)); 
    });

有关此内容的更多信息,请参见this question的答案-仅将两个数组作为输入处理。

答案 1 :(得分:0)

您可以获取第一个索引数组,并将其与其他每个数组进行匹配,并相应地过滤值

const arr1 = [5, 10, 15, 20];
const arr2 = [15, 88, 1, 5, 7];
const arr3 = [1, 10, 15, 5, 20];

const intersection = (arr) => {
  let [a,...rest] = arr
  return a.filter(v=> rest.every(val => val.includes(v)))
}

console.log(intersection([arr1, arr2, arr3]));

答案 2 :(得分:-1)

您可以在任何子数组上使用filter()。并在主数组上使用嵌套的every()

const arr1 = [5, 10, 15, 20];
const arr2 = [15, 88, 1, 5, 7];
const arr3 = [1, 10, 15, 5, 20];

const intersection = arr => arr[0].filter(x => arr.every(a => a.includes(x)));

console.log(intersection([arr1,arr2,arr3]))

说明:

查看代码:

arr[0].filter(x => arr.every(a => a.includes(x)));

对此的词解释。它仅过滤掉所有其他子数组中包含的第一个子数组(arr[0])中的那些元素。

Array.prototype.every()将回调作为参数。回调的第一个元素将是元素本身。在上述情况下,a将是arr1,arr2,arr3

arr.every(a => a.includes(x))检查是否第一个数组的当前元素。 5,10,15,20存在于所有其他数组中

以上版本中有嵌套循环。如果您想要更有效的解决方案,可以先将除第一个以外的所有数组转换为Set,然后使用Set.has

const arr1 = [5, 10, 15, 20];
const arr2 = [15, 88, 1, 5, 7];
const arr3 = [1, 10, 15, 5, 20];

const intersection = arr => {
  let [first,...rest] = arr;
  rest = rest.map(x => new Set(x));
  return first.filter(x => rest.every(a => a.has(x)));


} 
console.log(intersection([arr1,arr2,arr3]))