Javascriptで、配列に重複する値があるかどうかを確認するにはどうすればよいですか?


95

重複の可能性:
JavaScript配列内の重複値を見つける最も簡単な方法

配列に重複する値があるかどうかを確認するにはどうすればよいですか?

配列内のいくつかの要素が同じである場合は、trueを返します。それ以外の場合は、falseを返します。

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

重複を見つけることは気にしないことに注意してください。配列に重複が含まれているかどうかにかかわらず、ブール結果のみが必要です。



2
重複のリストを削除したくありません。リストに重複があるかどうかを知りたいだけです。
user847495 2011

7
この質問は重複していません。@ user847495は単に重複が存在するかどうかを確認したいだけなので、解決策は重複のすべての発生を見つけるために必要なものよりも速く/簡単です。たとえば、次のように実行できます。codr.io
v

2
アンダースコアを使用した簡単なテクニックvar test=['hello','goodbye','hello'] ; if ( test.length != _.unique(test).length ) { // some code }
Sai Ram

4
マークされた質問の複製ではありません。そのように質問をマークする前に注意を払ってください。
ジョンワイズ

回答:


222

ES2015環境(この記事の執筆時点:io.js、IE11、Chrome、Firefox、WebKitを毎晩)を使用している場合は、以下が機能し、高速になります(つまり、O(n))。

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

配列に文字列値のみが必要な場合は、次のように機能します。

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;
}

valuesSoFarこれまでに配列で確認した値をキーとする「ハッシュテーブル」を使用します。を使用してルックアップを実行し、inその値がすでに検出されているかどうかを確認します。もしそうなら、私たちはループから抜け出し、を返しtrueます。


文字列値以外でも機能する関数が必要な場合は、次の機能が機能しますが、パフォーマンスは劣ります。O(n )ではなくO(n 2)です。

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;
}

違いはvaluesSoFar、JavaScriptの「ハッシュテーブル」(つまりオブジェクト)には文字列キーしかないため、ハッシュテーブルの代わりに配列を使用することです。これは、のO(1)ルックアップ時間を失いin、代わりにのO(n)ルックアップ時間を取得することを意味しindexOfます。


3
あなたが与えた最初の例について。検証はまったく逆ではありませんか?関数に名前が付けられているhasDuplicates場合は、キャストの過程でセットのサイズが実際に縮小したかどうかを確認する必要があります。したがって、ブール演算子は、あるべき!==ではなく===
ティムDaubenschütz

pls編集。6文字以上変更していないので編集できません。
ティムDaubenschütz

1
MDNによると、IE11は、最初の例で使用されたコンストラクターをサポートしていません
adam77 2016

通常のJSのバージョンに戻りtrue、次の配列のために:[1, '1']
クナル

したがって、答えの前に「配列内の文字列値のみが必要な場合」。
ドメニック2018

4

別のアプローチ(配列1内のオブジェクト/配列要素の場合も)は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

も参照してください...

1には、JSONをサポートするブラウザー、またはサポートしていない場合はJSONライブラリが必要です。
2 編集:関数を使用して、簡単なチェックや重複する値の配列を返すことができるようになりました


3
知っておく価値のあるshowstopper以外の問題:1)ソートする元の配列を変更します。2)を区別しないnullNaNInfinity+Infinity、および-Infinity、3)プロトタイプが異なっていても、オブジェクトが同じ独自のプロパティを持っている場合、オブジェクトは等しいと見なされます。
ドメニック2011

1
@Domenic:うん、それについて言及すべきだった。元の配列の変異を回避するために編集されました。
KooiInc 2011

@Domenic:null / NaN / [+/-] Infinityを修正しました。編集を参照してください。
KooiInc 2011

@Domenic:問題3)は私にとって実際には問題ではありません。なぜなら、それはまさに私が望んでいることだからです。プロトタイプは気にせず、値だけを気にします。
畏敬の念

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.