何をしたいユーティリティか:「配列の重複削除」
ここでの「重複削除」は、同じ値が何度も入っている配列から、重複を取り除いて「一意な要素だけの配列」を作る処理です。
業務だと、こんな場面でよく出てきます。
- ユーザーが選んだ ID の一覧から、重複を消したい。
- CSV から読み込んだコード一覧をユニークにしたい。
- ログや集計で「種類の数」だけ知りたい。
毎回手書きでやるのではなく、「重複削除ユーティリティ」を 1 個決めておくと、コードが一気にスッキリします。
一番シンプルな重複削除:Set を使う
Set を使った基本形
プリミティブ値(数値・文字列・真偽値など)だけの配列なら、Set を使うのが一番簡単です。
function uniquePrimitive(array) {
if (!Array.isArray(array)) {
return [];
}
return Array.from(new Set(array));
}
JavaScript重要ポイントをかみ砕いて説明する
Set は「同じ値を 2 回入れても 1 回分しか持たない」コレクションです。
const s = new Set();
s.add(1);
s.add(1);
s.add(2);
s; // Set { 1, 2 }
JavaScriptこれをそのまま配列に戻すと、「重複のない配列」になります。
Array.from(new Set([1, 1, 2, 3, 3]));
// [1, 2, 3]
JavaScriptuniquePrimitive では、
「配列かどうかチェック → Set に通す → 配列に戻す」という流れを 1 行にまとめています。
実際の動き
uniquePrimitive([1, 1, 2, 3, 3]);
// [1, 2, 3]
uniquePrimitive(["a", "b", "a", "c"]);
// ["a", "b", "c"]
uniquePrimitive([true, false, true]);
// [true, false]
uniquePrimitive("not array");
// []
JavaScriptポイント:
Set は「値の同一性」で重複を判定しますが、オブジェクトや配列は「参照」が違えば別物として扱われます。
つまり、{ id: 1 } が 2 つあっても、Set 的には「別の要素」です。
オブジェクトの重複削除は、もう一段工夫が必要です。
オブジェクト配列の重複削除:キーを指定する
「id が同じなら同じもの」とみなしたい
業務では、こんな配列がよく出てきます。
const users = [
{ id: 1, name: "Alice" },
{ id: 1, name: "Alice (duplicate)" },
{ id: 2, name: "Bob" },
];
JavaScriptここで、「id が同じなら重複とみなして 1 件にしたい」という要件はよくあります。
この場合は、「どのプロパティを重複判定に使うか」をユーティリティに教えてあげる必要があります。
key を指定する uniqueByKey
function uniqueByKey(array, key) {
if (!Array.isArray(array)) {
return [];
}
const seen = new Set();
const result = [];
for (const item of array) {
if (item == null || typeof item !== "object") {
continue;
}
const value = item[key];
if (seen.has(value)) {
continue;
}
seen.add(value);
result.push(item);
}
return result;
}
JavaScriptuniqueByKey の重要ポイントを深掘りする
どの値で「見たことあるか」を判定するか
const seen = new Set();
const result = [];
JavaScriptseen は「すでに出てきたキーの値」を覚えておくための Set です。result は「重複を取り除いた結果配列」です。
配列を 1 件ずつ見ていく
for (const item of array) {
if (item == null || typeof item !== "object") {
continue;
}
const value = item[key];
if (seen.has(value)) {
continue;
}
seen.add(value);
result.push(item);
}
JavaScriptここでやっていることはシンプルです。
itemがオブジェクトでなければスキップ。item[key]を取り出す。- その値が
seenにすでにあれば「重複」とみなしてスキップ。 - なければ
seenに登録し、resultに追加。
これで、「指定したキーの値が同じものは 1 回だけ残す」動きになります。
実際の動き
const users = [
{ id: 1, name: "Alice" },
{ id: 1, name: "Alice (duplicate)" },
{ id: 2, name: "Bob" },
];
uniqueByKey(users, "id");
// [
// { id: 1, name: "Alice" },
// { id: 2, name: "Bob" },
// ]
JavaScript最初に出てきた id: 1 の要素だけが残り、
2 回目の id: 1 はスキップされています。
任意の「キー関数」で重複判定する
「複数項目の組み合わせ」で重複を決めたい場合
例えば、「code と version の組み合わせが同じなら重複」としたい場合、
単純な key 文字列では足りません。
そのときは、「要素から重複判定用のキーを作る関数」を渡せるようにします。
function uniqueBy(array, keyFn) {
if (!Array.isArray(array)) {
return [];
}
const seen = new Set();
const result = [];
for (const item of array) {
const key = keyFn(item);
if (seen.has(key)) {
continue;
}
seen.add(key);
result.push(item);
}
return result;
}
JavaScript実際の使い方
const items = [
{ code: "A", version: 1 },
{ code: "A", version: 1 },
{ code: "A", version: 2 },
{ code: "B", version: 1 },
];
const unique = uniqueBy(items, (item) => `${item.code}:${item.version}`);
// [
// { code: "A", version: 1 },
// { code: "A", version: 2 },
// { code: "B", version: 1 },
// ]
JavaScriptkeyFn の中で、
「重複判定に使いたい情報」を文字列などにまとめて返してあげれば OK です。
実務で意識してほしい設計のポイント
「何をもって同じとみなすか」をはっきりさせる
重複削除は、「同じとは何か?」を決める作業でもあります。
- プリミティブ配列なら「値が同じなら同じ」。
- オブジェクト配列なら「id が同じなら同じ」。
- 場合によっては「code+version の組み合わせが同じなら同じ」。
これを曖昧にしたまま書き始めると、
あとから「このケースは別扱いにしたい」といった例外が増えていきます。
ユーティリティとして、
uniquePrimitive
uniqueByKey
uniqueBy
JavaScriptのように「ルールごとに関数を分ける」と、
コードを読む人にも意図が伝わりやすくなります。
順序をどう扱うか
ここまでの実装は、「最初に出てきた要素を残し、後から出てきた重複を捨てる」動きです。
これは多くの業務では自然な挙動ですが、
「最後に出てきたものを優先したい」ケースもあります。
その場合は、ループを逆順に回すか、Map を使って「キー → 要素」を上書きしていく実装に変える、などの工夫が必要です。
パフォーマンスを意識するタイミング
Set や Map を使った重複削除は、
基本的に「配列の長さに比例する時間」で終わります(O(n))。
業務で扱う配列が数千〜数万件程度なら、
ほとんどの場合これで十分です。
もし数十万〜数百万件レベルになってきたら、
- そもそもそんなに一度にメモリに載せる設計でよいのか
- サーバ側でユニークにしてから渡せないか
といった、もう一段上の設計を見直すタイミングです。
少し手を動かして感覚をつかむ
コンソールで、次のようなコードを実際に打ってみてください。
uniquePrimitive([1, 1, 2, 3, 3]);
uniquePrimitive(["a", "b", "a", "c"]);
const users = [
{ id: 1, name: "Alice" },
{ id: 1, name: "Alice (duplicate)" },
{ id: 2, name: "Bob" },
];
uniqueByKey(users, "id");
const items = [
{ code: "A", version: 1 },
{ code: "A", version: 1 },
{ code: "A", version: 2 },
{ code: "B", version: 1 },
];
uniqueBy(items, (item) => `${item.code}:${item.version}`);
JavaScript「どの要素が残り、どの要素が捨てられているか」を自分の目で確認してみてください。
そのうえで、自分のプロジェクトに
export function uniquePrimitive(...) { ... }
export function uniqueByKey(...) { ... }
export function uniqueBy(...) { ... }
JavaScriptを置き、
「配列の重複を消したくなったら、必ずこの“重複削除ユーティリティ”を通す」
というルールを作ってみてください。
それだけで、あなたの配列処理は、場当たり的な for 文の寄せ集めから、
意図と一貫性を備えた「業務レベルの配列ユーティリティ」に変わっていきます。

