【问题标题】:Determining whether an array contains duplicate values判断一个数组是否包含重复值
【发布时间】:2014-10-10 23:05:33
【问题描述】:

我想扫描一个 JS 数组并确定是否所有元素都是唯一的,或者该数组是否包含重复项。

例子:

my_array1 = [1, 2, 3] 
my_array2 = [1, 1, 1]

我想得到这样的结果:

my_array1 must be return true, because this array element is unique
and array2 must be return false, because this array element is not unique

我该如何编写这个方法?

【问题讨论】:

标签: javascript jquery arrays


【解决方案1】:

首先对数组进行排序,然后进行简单的比较循环。

function checkIfArrayIsUnique(arr)  {
   var myArray = arr.sort();

    for (var i = 0; i < myArray.length; i++) {
        if (myArray.indexOf(myArray[i]) !== myArray.lastIndexOf(myArray[i])) { 
            return false; 
        } 
    } 

    return true;
}

【讨论】:

  • 这是一个很好的解决方案。用最后一个索引检查第一个索引是有效的,尽管仅供参考 .sort() 不会返回一个新数组,它只是修改正在排序的数组/对象。
  • 现在我想起来了,你甚至不需要对它进行排序就能得到同样正确的结果。
  • 为什么需要事先对数组进行排序?
【解决方案2】:

如果您想检查唯一性,您可以这样做。正如评论中所述,我不认为这是唯一的最佳选择。下面有一些很好的答案。

var arr = [2,3,4,6,7,8,9];
var uniq = []; // we will use this to store the unique numbers found
               // in the process for doing the comparison

var result = arr.slice(0).every(function(item, index, array){
  if(uniq.indexOf(item) > -1){
    // short circuit the loop
    array.length=0; //(B)
    return false;
  }else{
    uniq.push(item);
    return true;
  }
});

result --> true

arr.slice(0) 创建数组的临时副本,在其上完成实际处理。这是因为当满足唯一性标准时,我清除数组 (B) 以使循环短路。这将确保处理满足条件后立即停止。

如果我们将它作为一个方法暴露在一个 Array 实例上会更好。 所以我们可以做这样的事情[1,2,3,5,7].isUnique();

添加下面的sn-p就可以了

Array.prototype.isUnique = function() {
    var uniq = [];
    var result = this.slice(0).every(function(item, index, arr) {
        if (uniq.indexOf(item) > -1) {
            arr.length = 0;
            return false;
        } else {
            uniq.push(item);
            return true;
        }
    });
    return result;
};

arr.isUnique() --> true

DEMO

【讨论】:

  • 扫描一个JS数组,判断所有元素是否唯一,或者数组是否包含重复,我们不需要循环。我们可以对数组进行排序,检查数组的第一个和最后一个元素机器......这不是最好的方法
  • @timus2001:谢谢。我没有建议它作为最佳选择。但只是将其添加为许多其他好的答案的替代方法之一。
【解决方案3】:

你可以这样尝试:

function uniqueArray(arr) {
    var hash = {}, result = [];
    for ( var i = 0, l = arr.length; i < l; ++i ) {
        if ( !hash.hasOwnProperty(arr[i]) ) { 
            hash[ arr[i] ] = true;
            result.push(arr[i]);
        }
    }
    return result;
}

【讨论】:

  • 我确实喜欢跟踪迄今为止在地图中看到的值的方法,但这并不能真正解决 OP 的问题。这需要一个数组并返回一个仅包含唯一值的新数组。问题是请求一个返回布尔值的方法,指示给定数组是否包含重复项。
【解决方案4】:

试试这个:-

var my_array1 = [1, 2, 3] 
var my_array2 = [1, 1, 1]


function isUnique(obj)
{
   var unique=obj.filter(function(itm,i,a){
      return i==a.indexOf(itm);
   });   
   return unique.length == obj.length;  
 }


 alert(isUnique(my_array1))
 alert(isUnique(my_array2))

Demo

【讨论】:

  • ?true:false 严重
【解决方案5】:

我觉得你可以试试Underscore js,一个强大的javascript库

下划线使用示例

function checkUniqueArr(arr){
   var unique_arr = _.uniq(arr);
   return arr.length == unique_arr.length;
}

【讨论】:

  • 问题标记为 jQuery not Underscore。
  • 是的,我明白了。但我认为这也是用户的解决方案。感谢您的评论。
【解决方案6】:

测试唯一性最有效的方法是:

function isUnique(arr) {
  for(var i = 0; i < arr.length; i++) {
    if (arr.indexOf(arr[i]) != i) return false;
  }
  return true;
}

这是O(n2) 在最坏的情况下。多数情况下不需要完成对非唯一数组的扫描。

【讨论】:

  • 很高兴看到用大 O 符号思考的答案:D
  • 实际上,在最坏的情况下,这将是O(n^2)。你假设indexOfO(1),但是想想它在做什么——它遍历整个数组(大小n)来寻找匹配。即使您看不到循环,它实际上仍然是一个嵌套循环。
【解决方案7】:
function containsDuplicates(arr) {
    var seen = {};
    var duplicate = false;

    for (var i = 0; i < arr.length; i++) {
        if (seen[arr[i]]) {
            duplicate = true;
            break;
        }
        seen[arr[i]] = true;
    }

    return duplicate;
}

jsFiddle

最佳情况:O(1) 时间和空间 - 第二个元素是重复的
平均/最坏情况:O(n) 时间和空间 - 没有重复,或者重复在中间

这里的许多答案似乎都依赖于数组方法的一些复杂散布,这些方法本质上是迭代的,并且通常似乎不适合这个相当简单的任务。从算法上讲,这个问题可以在O(n) 时间内解决,但是indexOf/filter/map(或类似的数组方法)在for 循环中的任何嵌套都意味着您的计算时间将会增加(充其量) ) 与您的数组大小成二次方,而不是线性地。这在时间上是低效的。

现在,一般来说,微优化实际上是没有必要的,除非您已确定这是您应用程序的性能瓶颈。但在我看来,这种算法是您在开始编码之前设计的(以伪代码形式)并与应用程序的需求相匹配。如果您的数组中有一个庞大的数据集,您可能会很高兴不必多次查看它来获得答案。当然,这里需要注意的是,您是在用时间复杂度换取空间复杂度,因为我的解决方案需要 O(n) 空间来缓存以前看到的值。

【讨论】:

    【解决方案8】:
    If you need to check all element are unique then following will do the trick
    
    <script>
    my_array1 = [11, 20, 3] 
    my_array2 = [11, 11, 11]
    var sorted1= my_array1.sort();
    var sorted2= my_array2.sort();
    if(sorted1[0]==sorted1[sorted1.length-1])
        alert('all same');
    if(sorted2[0]==sorted2[sorted2.length-1])
        alert('all same');
    
    </script>
    

    【讨论】:

      【解决方案9】:

      我刚刚想出了这个答案。 我正在准备面试。 我认为这是坚如磐石。

      let r  = [1,9,2,3,8];
      let r2 = [9,3,6,3,8];
      
      let isThereDuplicates= r.slice().sort().some((item,index,ar)=>(item ===ar[index+1]));
      console.log('r is: ',isThereDuplicates) // -> false. All numbers are unique
      
      isThereDuplicates=  r2.slice().sort().some((item,index,ar)=>(item ===ar[index+1]));
      console.log('r2 is: ',isThereDuplicates) //->true. 3 is duplicated
      

      我首先对原始数组进行切片和排序。

      r.slice().sort()
      

      然后我检查至少一个项目,项目等于数组中的下一个项目。

      .some((item,index,array)=>
          item === array[index+1]
      );
      

      【讨论】:

        猜你喜欢
        • 2020-01-22
        • 2014-01-22
        • 1970-01-01
        • 1970-01-01
        • 2014-06-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-28
        相关资源
        最近更新 更多