たとえばJavaScriptで配列を扱っているとき、、、
- 同じ値を含めたくない、
- 重複してないか確認したい
、、、みたいな場面がありました。
一番簡単なのは forEach を使うことですが、あんまりスマートじゃありません。
そこで、JSにおける配列の重複チェックの簡単&スマートなやり方 をいくつか紹介
たぶん重複チェックするだけなら、最初のが一番スマートだと思います。
方法1.Setを使って重複チェックするやり方
その一番スマートなやり方とはコレ
Setオブジェクトを使って重複してるか調べる方法
これ以上に楽に判定できるやり方って(たぶん)ないですね。
この Set ですが、ES6 から使えるようになったデータ型です。
▼ MDNでの Set についての説明
Set オブジェクトは値のコレクションです。挿入順に要素を反復することができます。Set に重複する値は格納出来ません。Set 内の値はコレクション内で一意となります。
また、NaN と undefined も Set 内に格納できます。NaN は(NaN !== NaN ですが)NaN と同じと扱われます。
引用元 : https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Set
『Set に重複する値は格納出来ません』
この一文さえ見れば、賢い人ならあとはすべて分かるはず
そうです。配列を Set に変換し、元配列と長さ(length)が違えば重複があると分かる という訳です。
面白そうなので、早速そのようなコードを書いてみました。
▼ 配列の重複を調べてる関数コード
1 2 3 4 5 |
/** 配列内で値が重複してないか調べる **/ function existsSameValue(a){ var s = new Set(a); return s.size != a.length; } |
コードの通り new Set(a) で Set型に変換し、その長さと元配列長さが等しくないかを返すもの。つまり異なるなら true なので重複してると分かる訳です。
ただし Set では length が常に 0 になるので、size を使うことに要注意
実際にこの関数を使った結果は次の通り
▼ まず文字列配列で試してみた
1 2 3 4 5 6 7 |
var arr = [ 'j', 'a', 'v', 'a', 's', 'c', 'r', 'p', 't' ]; console.log(existsSameValue(arr)); /// => true |
▼ 数値配列でも試してみた
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
var arr = [2, 4, 8, 16, 32, 64, 128]; console.log(existsSameValue(arr)); /// => false var arr = [2, 4, 6, 8, 0, 2, 4]; console.log(existsSameValue(arr)); /// => true var arr = [NaN, NaN, NaN]; console.log(existsSameValue(arr)); /// => true var arr = [undefined, undefined , undefined]; console.log(existsSameValue(arr)); /// => true |
数値の場合は NaN だけには注意が必要かも
普通は
NaN != NaN になるけど、Set 内では同じものとして扱われてしまいます。
あと
undefined を含むなら、
undefined 同士は異なるものとして認識される模様です。
方法2.重複チェックをforEachでやるやり方も紹介
今紹介した Set のやり方はかなりスマート
でも ES6 以降なので、互換性を気にすると少し使いにくいかもしれません。
▼ ブラウザので対応状況
上ページに対応状況が表に載ってるけど、IEだとほぼ対応してないです。
切り捨てる選択肢もあるけど、日本はいまだにシェア率が高いからそれも難しいですね。
そこで forEach で地道に重複チェックする方法も紹介します。
やり方を箇条書きすると次の通り
- 配列を forEach で回す
- 現在値の indexOf の値を取得
- 現在値の lastIndexOf の値を取得
- indexOf と lastIndexOf の値比較
- もし違っていれば重複アリ
こういう感じで重複しているかを ゛地道に゛ チェック可能
ちなみにコード例として次みたいな関数を作ってみました。
▼ 具体的な関数例がコチラ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
/** 配列内で値が重複してないか調べる **/ function existsSameValue(arr){ var existsSame = false; arr.forEach(function(val){ /// 配列中で arr[i] が最初に出てくる位置を取得 var firstIndex = arr.indexOf(val); /// 配列中で arr[i] が最後に出てくる位置を取得 var lastIndex = arr.lastIndexOf(val); if(firstIndex !== lastIndex){ /// 重複していたら true を返す existsSame = true; } }) return existsSame; } |
▼ この関数を使って重複チェックしてみた
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
var arr = [ 'j', 'a', 'v', 'a', 's', 'c', 'r', 'p', 't' ]; console.log(existsSameValue(arr)); /// => true var arr = [2, 4, 8, 16, 32, 64, 128]; console.log(existsSameValue(arr)); /// => false var arr = [2, 4, 6, 8, 0, 2, 4]; console.log(existsSameValue(arr)); /// => true |
チャンと期待通りの結果になってます。
ES6が使用できない環境なら、この方法もありかもしれません。
ここまでのまとめ
ということで、一番楽&スマートに配列重複チェックする方法でした。
もし「もっといい方法あるよ」、という方はぜひコメントください。ではまた