【问题标题】:Javascript Get the common elements of three arraysJavascript 获取三个数组的共同元素
【发布时间】:2021-11-27 13:49:30
【问题描述】:

我正在尝试过滤 3 个数组的公共元素。但不是获取 3 个数组的公共元素,它只读取 2 个数组而不是第 3 个数组。这是我的代码,谢谢:

function commonElementsOfArray(arr1, arr2, arr3) {
    return arr1.filter(function (n) {
        return arr2.indexOf(n) !== -1;
        return arr3.indexOf(n) !== -1;
    });
}

【问题讨论】:

  • 您有一个包含两个return 语句的函数。只需结合这两个条件,只使用一个return。这是一个示例:return arr2.indexOf(n) !== -1 && arr3.indexOf(n) !== -1
  • @ejade ...关于所有提供的答案/解决方案/方法,还有什么问题吗?
  • @ejade ... 在 SO 这被认为是得到帮助的人的一个很好的姿态,提供一些反馈和/或对答案进行投票和/或接受最重要的答案有助于解决 OP 的问题。
  • 完成。谢谢

标签: javascript arrays intersection


【解决方案1】:

正如@Titus 所述,您代码中的问题是双重return 语句-一旦找到第一个return,过滤器函数将退出。

但是,在您查找有关Array.indexOf 的共同元素的方法中,还有一个问题值得指出。问题是Array.indexOfO(n) 操作,这意味着将针对arr2 的每个元素和arr3 的每个元素检查参数。从表面上看,这听起来像是正确的方法,但如果数组很大,那么这将是一个非常缓慢的函数。例如,如果每个数组有 1,000 个条目 (n),那么您的函数将获取每个元素并与 arr2 和 arr3 (n) 中的所有内容进行比较。导致O(n^2) 时间复杂度。

另一种方法是创建一个Map 并在您遍历每个数组时填充它,以跟踪条目被看到的次数。查找值现在有 O(1) 运行时。遍历每个产生 O(n) 的数组仍然有成本,但由于快速查找,这变成了 n * 1 操作或 O(n) 时间复杂度。

function commonElementsOfArray(arr1, arr2, arr3) {
  const map = new Map();
  const updateMap = arr => {
    arr.forEach(entry => {
      if (!map.has(entry)) {
        map.set(entry, 1);
      } else {
        let timesSeen = map.get(entry);
        map.set(entry, ++timesSeen);
      }
    });
  };

  updateMap(arr1);
  updateMap(arr2);
  updateMap(arr3);

  map.forEach((count, key) => {
    // remove all entries not seen at least 3 times
    if (count !== 3) {
      map.delete(key);
    }
  });

  return [...map.keys()];
}

console.log(commonElementsOfArray([1, 2, 3], [1, 2, 4], [2, 4, 5]));

【讨论】:

    【解决方案2】:

    如何将 OP 的代码重构为通用交集功能,该功能实现两个数组的简化交集函数,并通过处理通用函数(数组类型)参数的reduce 任务生成超过 2 个数组的整体交集?

    因此,两个数组的交集将基于 OP 的代码 filter 方法,但使用 includes 而不是 indexOf。有点像...

    function getIntersectionOfTwo(a, b) {
      return a.filter(function (n) {
        return b.includes(n);
      });
    }
    

    然后,一个通用的getIntersection 只需要确保其参数的类型安全性和正确的返回值,以及正确提供的最小数量的参数的交集结果......

    function getIntersection(...listOfArrays) {
      function getIntersectionOfTwo(a, b) {
        return a.filter(function (n) {
          return b.includes(n);
        });
      }
      // assure only array type arguments.
      listOfArrays = listOfArrays.filter(Array.isArray);
    
      return (listOfArrays[1] ?? listOfArrays[0])
        && listOfArrays.reduce(getIntersectionOfTwo);   
    }
    
    console.log(
      'getIntersection() ...',
      getIntersection()
    );
    console.log(
      'getIntersection(9, "foo", 0) ...',
      getIntersection(9, "foo", 0)
    );
    console.log(
      'getIntersection([2, 7, 0], "bar") ...',
      getIntersection([2, 7, 0], "bar")
    );
    console.log(
      'getIntersection([2, 7, 0, 4], [6, 2, 7, 3]) ...',
      getIntersection([2, 7, 0, 4], [6, 2, 7, 3])
    );
    console.log(
      'getIntersection([2, 7, 0, 4], [6, 2, 7, 3], [9, 1, 2]) ...',
      getIntersection([2, 7, 0, 4], [6, 2, 7, 3], [9, 1, 2])
    );
    console.log(
      'getIntersection([2, 7, 0, 4], [6, 2, 7, 3], [9]) ...',
      getIntersection([2, 7, 0, 4], [6, 2, 7, 3], [9])
    );
    .as-console-wrapper { min-height: 100%!important; top: 0; }

    上面例子中getIntersectionOfTwo of cause 的实现保持简单,以便更好地理解整个任务的重构过程。

    在下一个重构步骤中,该功能也可以得到改进,以便更有效地处理/处理大量数组数据。因此,可以在filter 回调中使用基于Map 的查找,而不是在每个filter 迭代中搜索b.includes(n)

    function getIntersection(...listOfArrays) {
      function getIntersectionOfTwo(intersection, iterableItem) {
        // in order to compare huge arrays more efficiently access ...
        const [
    
          comparisonBase, // ... the shorter one as comparison base
          comparisonList, // ... and the longer one to filter from.
    
        ] = [intersection, iterableItem]
          .sort((a, b) => a.length - b.length);
    
        // create a `Map` based lookup table from the shorter array.
        const itemLookup = comparisonBase
          .reduce((map, item) => map.set(item, true), new Map)
    
        // the intersection is the result of following filter task.
        return comparisonList.filter(item => itemLookup.has(item));
      }
      // assure only array type arguments.
      listOfArrays = listOfArrays.filter(Array.isArray);
    
      return (listOfArrays[1] ?? listOfArrays[0])
        && listOfArrays.reduce(getIntersectionOfTwo);   
    }
    
    console.log(
      'getIntersection() ...',
      getIntersection()
    );
    console.log(
      'getIntersection(9, "foo", 0) ...',
      getIntersection(9, "foo", 0)
    );
    console.log(
      'getIntersection([2, 7, 0], "bar") ...',
      getIntersection([2, 7, 0], "bar")
    );
    console.log(
      'getIntersection([2, 7, 0, 4], [6, 2, 7, 3]) ...',
      getIntersection([2, 7, 0, 4], [6, 2, 7, 3])
    );
    console.log(
      'getIntersection([2, 7, 0, 4], [6, 2, 7, 3], [9, 1, 2]) ...',
      getIntersection([2, 7, 0, 4], [6, 2, 7, 3], [9, 1, 2])
    );
    console.log(
      'getIntersection([2, 7, 0, 4], [6, 2, 7, 3], [9]) ...',
      getIntersection([2, 7, 0, 4], [6, 2, 7, 3], [9])
    );
    .as-console-wrapper { min-height: 100%!important; top: 0; }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-06-27
      • 1970-01-01
      • 1970-01-01
      • 2018-01-24
      • 1970-01-01
      • 2021-09-21
      • 1970-01-01
      • 2023-03-26
      相关资源
      最近更新 更多