【问题标题】:JavaScript: Use Reduce () to construct a function intersection that compares input arrays; return intersecting elements onlyJavaScript:使用Reduce()构造函数交集,比较输入数组;只返回相交的元素
【发布时间】:2019-10-29 08:39:52
【问题描述】:

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

我的解决方案可行,但很麻烦:

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() 并且效率更高的替代代码解决方案吗?

如果您能评论代码的每一行所做的事情以帮助我理解,我将不胜感激。

【问题讨论】:

    标签: javascript function return reduce


    【解决方案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 存在于所有其他数组中

    以上版本有嵌套循环。如果您想要更有效的解决方案,您可以先将除 first 之外的所有数组转换为 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]))

    【讨论】:

    • 谢谢;下面的代码在做什么? x => arr.every(a => a.includes(x))
    • @PineNuts0 我已经添加了解释。有什么不懂的可以问一下。
    • 奇怪,问题是关于使用reduce,这个答案被接受了。我很困惑。
    • @trincot 好吧,我不知道为什么会这样。有时新用户不太了解高阶数组方法。他们只知道其中一个人的名字,并在问题中提出这个问题。他们不知道最适合他们目的的方法。
    【解决方案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 的答案——仅处理两个数组作为输入。

    【讨论】:

    • 我有点困惑:下面的代码在做什么? a.filter(c => b.some(d => c === d))
    • @PineNuts0, filter 迭代 a 数组,并返回一个新数组,其中包含表达式 b.some(d => c === d) 为真的值。 b.some 迭代另一个数组b,并在至少找到满足c === d 的元素时返回true。
    【解决方案3】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-10
      • 1970-01-01
      • 2020-05-10
      • 1970-01-01
      • 2019-01-08
      • 2010-10-26
      相关资源
      最近更新 更多