【问题标题】:Find duplicate pairs in an array查找数组中的重复对
【发布时间】:2020-07-11 10:29:54
【问题描述】:

我有一个数组a = [1,1,1,2,2,3,3,3,4,4,4,6,6,6,7,7] 我想获取此数组列表中的所有重复对。 由于有 2 和 7 对,输出应该是 -

输出:[2, 7]

我尝试编写自己的逻辑,但我在这方面非常薄弱。有人可以帮忙吗?

function getDuplicateArrayElements(arr){
let sorted_arr = arr.slice().sort();
let results = [];

for (let i = 0; i < sorted_arr.length; i++) {
    let matchingElementCount = 1;

    for (let j = i + 1; j < sorted_arr.length - i; j++) {
        if (sorted_arr[j] === sorted_arr[i]) {
            ++matchingElementCount;          
        } else {
            
            if(matchingElementCount % 2 === 0) {
                results.push(sorted_arr[i]);
            }
            i = j - 1;
            break;

        }
    }
}
return results; } var a = [1,1,1,2,2,3,3,3,4,6,6,6,7,7]; var duplicateValues= getDuplicateArrayElements(a);

【问题讨论】:

  • 为什么没有6?
  • 计算数组中每个值的个数,然后只保留计数为2的那些。
  • @Viney 我认为这是因为 6 出现了 3 次,而不是两次
  • 但是我可以有多个对,比如元素 1 重复 4 次,所以输出会有 [1,1]
  • 这对必须是连续的吗?就像如果最后有一个1,那么就会有四个1。那算两对吗?

标签: javascript node.js algorithm


【解决方案1】:

您可以使用reduceforEach 来实现您的结果。

const arr = [1,1,1,1,2,2,3,3,3,4,4,4,6,6,6,7,7];

// Generate a hashmap from the given array for counting the frequency.
const hashMap = arr.reduce((a, c) => {
  a[c] = (a[c] || 0) + 1;
  return a;
}, {});


const pair = [];

// If the frequency is divided by 2 then push the key of the hashMap into pair array.
Object.entries(hashMap).forEach(([k, v]) => {
  if (v % 2 === 0) {
    [...Array(Math.floor(v / 2))].forEach(_ => pair.push(k));
  }
})

console.log(pair);

【讨论】:

  • 你为什么用([k, v)]而不是(k,v)
  • Object.entries() 为您提供了一个数组数组,例如[[k1, v1], [k2, v2], ...]。这就是我使用这种方式的原因。
  • @MenaiAlaEddine-Aladdin 他们是destructuring第一个参数
  • @adiga,干净的答案。
  • 这仅包括重复两次的项目。 OP 在 cmets 中说:“如果 1 重复 4 次,输出将有 [1,1]
【解决方案2】:

您可以获取每个数字的频率,然后过滤掉任何具有奇数频率的数字。然后,您可以.flatMap() 将频率添加到一个数组中,该数组包含您找到的每一对的编号,如下所示:

const a = [1,1,1,2,2,3,3,3,4,4,4,6,6,6,7,7];
const freq = a.reduce((m, n) => m.set(n, (m.get(n) || 0) + 1), new Map);
const res = [...freq].filter(([n, count]) => count % 2 == 0).flatMap(([n, c]) => Array(c/2).fill(n));
console.log(res);

这样,如果您有四个 1(即:两对 1),过滤器将拾取它,允许您将 [1, 4] 数组平面映射到 [1, 1] 数组,合并到更大的结果数组中。

【讨论】:

  • 使用Map 代替Object 有什么好处吗?我的意思是map.getsomeObject.somekey 快吗?
  • @RameshReddy reduce 的一个优点是map.set 返回 Map 对象本身。如果是对象累加器,您必须设置属性并在单独的行中返回,或者使用 comma operator 之类的东西进行隐式返回
  • @RameshReddy 可能会快一点,但我还没有测试过。 Map 与 reduce 配合得很好,因为 m.set() 将返回新修改的 map,然后在下一次迭代中继续作为累加器的下一个值。使用对象也适用于 reduce,但 for 循环可能会更好 - 但这值得商榷(你可以观看 this 视频,了解我为什么决定在这里使用地图)跨度>
  • @RameshReddy 不仅如此。 Map 迭代其内容以插入它们。如果 OP 的原始数组是 [7,7,1,1],带有对象累加器,则输出将是 [1, 7],但对于 Map,它将以正确的顺序为 [7, 1]。这是因为 integer keys are enumerated in ascending order 用于对象。 Map 保持插入顺序。
【解决方案3】:

您可以创建一个辅助映射并将每个数字的计数作为值,将数字本身作为键。遍历数组后,只需找到计数可被2 整除的那些:

var a = [1, 1, 1, 2, 2, 3, 3, 3, 4, 6, 6, 6, 7, 7]

function findDuplicates(arr) {

    const map = {};

    for (const curr of arr) {
        if (!map[curr]) {
            map[curr] = 0;
        }
        map[curr]++;
    }
    const res = [];
    for (const key in map) {
        if (map.hasOwnProperty(key) && map[key] % 2 === 0) {
            res.push(Number.parseInt(key));
        }
    }
    return res;
}

console.log(findDuplicates(a));

【讨论】:

    【解决方案4】:

    您可以先计算每个数字的出现次数,如果它大于 0 且可被 2 整除,则将这些添加到最终结果中,否则不要

    function getDuplicateArrayElements(arr) {
      let map = {}
      let results = [];
    
      for (let num of arr) {
        map[num] = map[num] || 0
        map[num]++
      }
      
      return Object.keys(map)
                   .filter(v => map[v] && map[v] % 2 === 0)
                   .map(v => new Array(map[v]/2).fill(+v))
                   .flat()
                   .sort()
    }
    
    var a = [1, 1, 1, 2, 2, 3, 3, 3, 4, 6, 6, 6, 7, 7,8,8,8,8];
    var duplicateValues = getDuplicateArrayElements(a);
    console.log(duplicateValues)

    【讨论】:

    • 哇,你几乎调用了 Array 的所有 HOF。
    • @MenaiAlaEddine-Aladdin 哈哈哈好一个,如果不需要对输出进行排序,您可以放弃排序,map + flat 可以像其他答案中所做的那样被 flatMap 替换,但效果不大差异
    【解决方案5】:
    const a = {};
    [1,1,1,2,2,3,3,3,4,6,6,6,7,7].forEach(v => {a[v] = a[v] ? a[v] + 1 : 1});
    const l = [];
    Object.keys(a).forEach(k => !(a[k] % 2) && l.push(k));
    

    【讨论】:

    • 虽然此代码可能提供问题的解决方案,但强烈建议您提供有关此代码为何和/或如何回答问题的附加上下文。从长远来看,只有代码的答案通常会变得毫无用处,因为未来遇到类似问题的观众无法理解解决方案背后的原因。
    【解决方案6】:

    给你:

     function getDuplicateArrayElements(arr){
        var dupilcates=arr.filter(x =>  arr.filter(y=>y==x).length==2);  
        var found=[];
        for(var i=0;i<dupilcates.length;i=i+2)
          found.push(dupilcates[i]);
        return found;
    }
    

    【讨论】:

      【解决方案7】:

      这将为您提供所需的配对。输入[1, 1, 1, 1, 2, 2, 3, 3, 3, 4, 6, 6, 6, 6, 7, 7] 将返回[1,1,2,6,6,7]

      function getDuplicateArrayElements(arr){
        let sorted_arr = arr.slice().sort();
        let results = [];
        let i = 0;
        while (i < sorted_arr.length) {
          let counter = 1;
          let j = i;
          while (sorted_arr[j] === sorted_arr[j+1]) {
            counter++;
            j++;
          }
          
          if (counter%2 == 0) {        
            results.push(...Array(counter/2).fill(sorted_arr[i]))
          }
          
          i += counter;
        }
      
        return results; 
      } 
      
      var a = [1, 1, 1, 1, 2, 2, 3, 3, 3, 4, 6, 6, 6, 6, 7, 7];
      console.log(getDuplicateArrayElements(a));

      【讨论】:

        【解决方案8】:

        另一个相当简洁的解决方案:

        a = [1,1,1,2,2,3,3,3,4,4,4,6,6,6,7,7];
        uniques = new Set(a); //filter out duplicates
        res = [];
        uniques.forEach((key)=>{
        if(a.filter(elem => elem === key).length === 2){res.push(key)}; 
        //filter out only the elements which match the key being tested
        //if there are 2, push to result
        })
        

        编辑:更简洁,但效率可能更低:

        a = [1,1,1,2,2,3,3,3,4,4,4,6,6,6,7,7];
        res = Array.from(new Set(a.filter(elem => a.filter(el => el === elem).length === 2)));
        

        【讨论】:

          【解决方案9】:

          Javascript 有很棒的 JSON 对象,在我看来,你可以使用 json 作为字典;

          { key: _value }.
          循环抛出数组一次,不排序,不切片

          key是数组的元素值,_value是频率

          var frequencies = {};
          for (let i = 0; i < a.length; a++) {
             if (result[a[i]] == 'over') continue;
             if (result[a[i]] == undefined) { // First times
                 result[a[i]] = 1
             } else if (result[a[i]] == 1) { // Second times
                 result[a[i]] = 2
             } else { // Ignore if > 2
                 result[a[i]] = 'over'
             }
          }
          // result: {1: "over", 2: 2, 3: "over", 4: "over", 6: "over", 7: 2}
          

          所以现在选择键的值等于 2

          【讨论】:

            【解决方案10】:
            function getDuplicateArrayElements(numbers: number[]): number[] {
              const occurences = new Map<number, number>();
            
              for (let number of numbers) {
                if (occurences.has(number)) {
                  const current = occurences.get(number)!;
                  occurences.set(number, current + 1);
                } else 
                occurences.set(number, 1)  
              }
            
              return (
                Array
                  .from(occurences.entries())
                  .reduce<number[]>(
                    (accumulator, [key, value]) => {
                      if (value === 2) {
                        return accumulator.concat(key)
                      }
            
                      return accumulator
                    },
                    []
                  )
              )
            }
            
            const a = [1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 6, 6, 6, 7, 7];
            
            getDuplicateArrayElements(a); // [2, 7]
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2018-11-21
              • 2018-08-13
              • 2014-08-08
              • 2016-04-17
              • 2018-12-18
              • 1970-01-01
              • 2012-08-26
              相关资源
              最近更新 更多