Trong Javascript, làm cách nào để kiểm tra xem một mảng có các giá trị trùng lặp hay không?


95

Có thể trùng lặp:
Cách dễ nhất để tìm các giá trị trùng lặp trong một mảng javascript

Làm cách nào để kiểm tra xem một mảng có các giá trị trùng lặp không?

Nếu một số phần tử trong mảng giống nhau, thì trả về true. Nếu không, trả về false.

['hello','goodbye','hey'] //return false because no duplicates exist
['hello','goodbye','hello'] // return true because duplicates exist

Lưu ý rằng tôi không quan tâm đến việc tìm kiếm trùng lặp, chỉ muốn kết quả Boolean cho dù các mảng có chứa trùng lặp hay không.



2
Tôi không muốn xóa danh sách trùng lặp. Tôi chỉ muốn biết đúng hay sai nếu một danh sách có các bản sao trong đó.
user847495 11/09/11

7
Câu hỏi này không phải là một bản sao. Vì @ user847495 chỉ muốn kiểm tra xem các bản sao có tồn tại hay không, nên giải pháp nhanh hơn / dễ dàng hơn những gì cần thiết để tìm tất cả các lần xuất hiện của các bản sao. Ví dụ: bạn có thể làm điều này: codr.io/v/bvzxhqm
alden

2
sử dụng dấu gạch dưới , kỹ thuật đơn giảnvar test=['hello','goodbye','hello'] ; if ( test.length != _.unique(test).length ) { // some code }
Sai Ram

4
Không phải là bản sao của câu hỏi đã đánh dấu. Hãy chú ý trước khi đánh dấu các câu hỏi như vậy.
John Weisz

Câu trả lời:


222

Nếu bạn có môi trường ES2015 (theo văn bản này: io.js, IE11, Chrome, Firefox, WebKit hàng đêm), thì những điều sau sẽ hoạt động và sẽ nhanh (viz. O (n)):

function hasDuplicates(array) {
    return (new Set(array)).size !== array.length;
}

Nếu bạn chỉ cần các giá trị chuỗi trong mảng, thì cách sau sẽ hoạt động:

function hasDuplicates(array) {
    var valuesSoFar = Object.create(null);
    for (var i = 0; i < array.length; ++i) {
        var value = array[i];
        if (value in valuesSoFar) {
            return true;
        }
        valuesSoFar[value] = true;
    }
    return false;
}

Chúng tôi sử dụng một "bảng băm" valuesSoFarcó các khóa là các giá trị mà chúng tôi đã thấy trong mảng cho đến nay. Chúng tôi thực hiện tra cứu bằng cách sử dụng inđể xem liệu giá trị đó đã được phát hiện chưa; nếu vậy, chúng tôi giải cứu khỏi vòng lặp và quay trở lại true.


Nếu bạn cần một hàm hoạt động cho nhiều hơn các giá trị chuỗi, thì hàm sau sẽ hoạt động, nhưng không hiệu quả; đó là O (n 2 ) thay vì O (n).

function hasDuplicates(array) {
    var valuesSoFar = [];
    for (var i = 0; i < array.length; ++i) {
        var value = array[i];
        if (valuesSoFar.indexOf(value) !== -1) {
            return true;
        }
        valuesSoFar.push(value);
    }
    return false;
}

Sự khác biệt chỉ đơn giản là chúng ta sử dụng một mảng thay vì một bảng băm valuesSoFar, vì "bảng băm" JavaScript (tức là các đối tượng) chỉ có các khóa chuỗi. Điều này có nghĩa là chúng ta mất thời gian tra cứu O (1) của in, thay vào đó nhận được thời gian tra cứu O (n) của indexOf.


3
Về ví dụ đầu tiên bạn đưa ra. Không phải xác nhận chính xác theo cách khác? Nếu hàm của bạn được đặt tên hasDuplicates, thì nó sẽ kiểm tra xem kích thước của tập hợp có thực sự bị thu nhỏ trong quá trình truyền nó hay không? Do đó các nhà điều hành boolean nên !==và không===
Tim Daubenschütz

làm ơn chỉnh sửa. Tôi không thể chỉnh sửa vì tôi không thay đổi nhiều hơn 6 ký tự.
Tim Daubenschütz

1
Theo MDN IE11 không thực hiện việc hỗ trợ các nhà xây dựng được sử dụng trong ví dụ đầu tiên
adam77

Phiên bản JS bình thường trả về truecho mảng sau:[1, '1']
Kunal

Vì vậy, "nếu bạn chỉ cần giá trị chuỗi trong mảng" trước câu trả lời.
Domenic

4

Một cách tiếp cận khác (cũng dành cho các phần tử đối tượng / mảng trong mảng 1 ) có thể là 2 :

function chkDuplicates(arr,justCheck){
  var len = arr.length, tmp = {}, arrtmp = arr.slice(), dupes = [];
  arrtmp.sort();
  while(len--){
   var val = arrtmp[len];
   if (/nul|nan|infini/i.test(String(val))){
     val = String(val);
    }
    if (tmp[JSON.stringify(val)]){
       if (justCheck) {return true;}
       dupes.push(val);
    }
    tmp[JSON.stringify(val)] = true;
  }
  return justCheck ? false : dupes.length ? dupes : null;
}
//usages
chkDuplicates([1,2,3,4,5],true);                           //=> false
chkDuplicates([1,2,3,4,5,9,10,5,1,2],true);                //=> true
chkDuplicates([{a:1,b:2},1,2,3,4,{a:1,b:2},[1,2,3]],true); //=> true
chkDuplicates([null,1,2,3,4,{a:1,b:2},NaN],true);          //=> false
chkDuplicates([1,2,3,4,5,1,2]);                            //=> [1,2]
chkDuplicates([1,2,3,4,5]);                                //=> null

Xem thêm...

1 cần trình duyệt hỗ trợ JSON hoặc thư viện JSON nếu không.
2 chỉnh sửa: hàm hiện có thể được sử dụng để kiểm tra đơn giản hoặc trả về một mảng các giá trị trùng lặp


3
Các vấn đề không phải showstopper đáng lưu ý: 1) thay đổi mảng ban đầu được sắp xếp; 2) không phân biệt giữa null, NaN, Infinity, +Infinity, và -Infinity; 3) các đối tượng được coi là bình đẳng nếu chúng có cùng thuộc tính riêng, ngay cả khi chúng có các nguyên mẫu khác nhau.
Domenic

1
@Domenic: vâng, đáng lẽ phải đề cập đến nó. Đã chỉnh sửa để tránh đột biến của mảng ban đầu.
KooiInc

@Domenic: đã sửa cho null / NaN / [+/-] Infinity, xem các chỉnh sửa.
KooiInc

@Domenic: Vấn đề 3) thực ra không phải là vấn đề đối với tôi, vì nó chính xác là những gì tôi muốn. Tôi không quan tâm đến nguyên mẫu, chỉ quan tâm đến các giá trị.
kinh ngạc

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.