确定一个数组是否包含重复的值

7

我希望能够遍历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

如何编写这个方法?

看起来有很多其他的问题可以帮助你,你搜索过看看还有什么其他的吗?https://dev59.com/g2435IYBdhLWcg3wfgMf - Dan
9个回答

3
首先对数组进行排序,然后进行简单的比较循环。
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;
}

1
这是一个不错的解决方案。检查第一个索引和最后一个索引是高效的做法,但需要注意的是 .sort() 并不会返回一个新的数组,它只是修改正在排序的数组/对象。 - Derek
现在我想起来了,你甚至不需要排序就能得到相同的正确结果。 - Derek
为什么需要事先对数组进行排序? - Derek 朕會功夫

2
您可以尝试这样做:
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的问题。这将获取一个数组并返回一个仅包含唯一值的新数组。问题要求返回一个布尔值的方法,指示给定的数组是否包含重复项。 - nbrooks

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(); 添加以下代码片段即可开始使用。
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数组并确定所有元素是否唯一,或者数组是否包含重复项,我们不需要循环。我们可以对数组进行排序并检查数组的第一个和最后一个元素是否匹配...但这不是最好的方法。 - sumit
1
@timus2001:谢谢。我并不是将其提议为最佳选项,而只是将其作为众多其他好答案之一的替代方案添加进来。 - Prabhu Murthy

1

试试这个:

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


8
?true:false 这段代码是一个JavaScript中的条件运算符,也被称为三目运算符。它的作用是判断一个条件表达式是否为真,如果为真则返回true,否则返回false - Derek 朕會功夫

1
我认为您可以尝试使用强大的JavaScript库Underscore js
例如,使用Underscore的方法如下:
function checkUniqueArr(arr){
   var unique_arr = _.uniq(arr);
   return arr.length == unique_arr.length;
}

问题标记为jQuery而不是Underscore。 - Derek 朕會功夫
2
是的,我明白。但我认为这也是用户的解决方案。 感谢您的评论。 - fanfan1609

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

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

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

1
总是很棒看到答案使用大O符号来思考:D - Derek 朕會功夫
2
实际上,在最坏的情况下,这将是O(n^2)。您假设indexOfO(1),但请考虑它正在执行什么操作-它正在遍历整个数组(大小为n)搜索匹配项。即使您看不到循环,它仍然有效地是一个嵌套循环。 - nbrooks

1
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) 的空间来缓存先前看到的值。


0

我刚想出了这个答案。 我正在为面试做准备。 我认为这是非常可靠的。

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

0
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>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接