【问题标题】:How to 'properly' intersect two Arrays in Javascript [closed]如何在Javascript中“正确”相交两个数组[关闭]
【发布时间】:2017-02-17 19:50:11
【问题描述】:

有没有合适的方法在 Javascript 中相交两个数组?

我试图以正确的方式使两个数组相交,但我发现了一些困难

我的输入未按此处假设的方式排序 Simplest code for array intersection in javascript

我的代码:

/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number[]}
 */
var intersect = function(nums1, nums2) {
    var t, a = nums1,b = nums2;
    if (b.length > a.length) t = b, b = a, a = t;
    return a.filter(x => b.includes(x))
};
console.log(intersect([1, 2], [1, 1])); //[1] correct
console.log(intersect([1, 1], [1, 2])); //[1,1] wrong
console.log(intersect([1], [1, 1])); //[1,1] wrong
console.log(intersect([1, 1, 1], [1, 1])); //[1,1,1] wrong

并从该答案中尝试了该算法: Finding the intersection of two arrays in Javascript

/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number[]}
 */
var intersect = function(nums1, nums2) {
  var A=nums1,B=nums2;
  var m = A.reduce(function(m, v) { m[v] = 1; return m; }, {});
  return B.filter(function(v) { return m[v]; });
};
console.log(intersect([1, 2], [1, 1])); //[1,1] wrong
console.log(intersect([1, 1], [1, 2])); //[1] right
console.log(intersect([1], [1, 1])); //[1,1] wrong
console.log(intersect([1, 1, 1], [1, 1])); //[1,1] right
也试过这个:

/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number[]}
 */
var intersect = function(nums1, nums2) {
  return nums1.filter((n) => nums2.indexOf(n) !== -1);
};
console.log(intersect([1, 2], [1, 1])); //[1] right
console.log(intersect([1, 1], [1, 2])); //[1,1] wrong
console.log(intersect([1], [1, 1])); //[1] right
console.log(intersect([1, 1, 1], [1, 1])); //[1,1,1] wrong
还:

/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number[]}
 */
var intersect = function(nums1, nums2) {
  var a = nums1,b=nums2;
  var ai=0, bi=0;
  var result = [];

  while( ai < a.length && bi < b.length )
  {
     if      (a[ai] < b[bi] ){ ai++; }
     else if (a[ai] > b[bi] ){ bi++; }
     else /* they're equal */
     {
       result.push(a[ai]);
       ai++;
       bi++;
     }
  }

  return result;
};
console.log(intersect([1, 2], [1, 1])); //[1] right
console.log(intersect([1, 1], [1, 2])); //[1] right
console.log(intersect([1], [1, 1])); //[1] right
console.log(intersect([1, 1, 1], [1, 1])); //[1] right
console.log(intersect([2,1],[1,1])); //[] wrong

我错在哪里了?

【问题讨论】:

  • 我不确定你的问题的目的是什么。你期待什么样的答案?您希望人们“修复”这些实现中的每一个吗?
  • “相交”是什么意思?你的意思是将两个数组的所有值合并到一个数组中,还是将两个数组的所有唯一值复制到一个新的单个数组中,还是什么?
  • 为什么intersect([1, 1, 1], [1, 1]) 应该产生[1,1]?如果我们真的要删除重复项,那不应该返回[1]吗?
  • 是的,我在问为什么。在你弄清楚如何之前,你需要准确地解释what你在做什么。而且我认为这些测试用例还不够。

标签: javascript algorithm


【解决方案1】:
/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number[]}
 */
var intersect = function(nums1, nums2) {
    var arr = [], ind;
    while (nums1.length) {
        ind = nums2.indexOf(nums1.shift());
        if (ind > -1) {
            arr.push(nums2.splice(ind, 1)[0]);
        }
    }
    return arr;
};

【讨论】:

  • 完美且易于理解!
  • 你在残害nums2
  • @NinaScholz 是的,如果你不想删除 nums2,你可以创建它的副本copy2 = nums2.slice(0)
【解决方案2】:

您可以使用Map 并减少计数(如果找到用于过滤)。

var intersect = function(nums1, nums2) {
    var m = new Map();
    
    nums1.forEach(a => m.set(a, (m.get(a) || 0) + 1));
    return nums2.filter(a => m.get(a) && m.set(a, m.get(a) - 1));
};

console.log(intersect([1, 2], [1, 1]));    // [1]
console.log(intersect([1, 1], [1, 2]));    // [1]
console.log(intersect([1], [1, 1]));       // [1]
console.log(intersect([1, 1, 1], [1, 1])); // [1, 1]

【讨论】:

  • 最后一个应该返回[1, 1]。两个数组都包含 两个 1s.
  • 你能解释一下吗?
  • 如果值不是0,基本上它会计算每个元素和过滤器。然后减少计数。否则为 Array#filter 返回 false。
  • 你的代码“就像”魅力一样工作,不再打破它了吗?
  • +1 用于对你的辅助结构进行可怕但仍然很棒的持续突变,并将两个语句变成一个 &amp;&amp; 表达式,其中第二个子句仅用于它的突变侧-效果。约翰·巴克斯在某处哭泣。
【解决方案3】:

另一个实现,使用您的方法 1,但使用 ES 6 Set 删除重复项

    /**
     * @param {number[]} nums1
     * @param {number[]} nums2
     * @return {number[]}
     */
    var intersect = function(nums1, nums2) {
         var result = nums1.filter(x => nums2.includes(x));
         return [...new Set(result)];
    };

    console.log(intersect([1, 2], [1, 1])); //[1] correct
    console.log(intersect([1, 1], [1, 2])); //[1] correct
    console.log(intersect([1], [1, 1])); //[1] correct
    console.log(intersect([1, 1, 1], [1, 1])); //[1] correct
    console.log(intersect([1, 45, 143, 76, 11], [761,76, 11, 1])); //[1,76,11] correct

【讨论】:

  • [1, 1, 1], [1, 1] 应该返回 [1,1]
  • 你的交集逻辑是什么?
  • 结果中的每个元素出现的次数应与它在两个数组中显示的次数一样多。
  • 这和上面说的很不一样。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-12-15
  • 2012-08-23
  • 1970-01-01
  • 2018-09-02
  • 1970-01-01
  • 1970-01-01
  • 2013-08-31
相关资源
最近更新 更多