1
2

【JavaScript】連想配列の重複排除

Last updated at Posted at 2024-01-16

はじめに

JavaScriptの連想配列を加工してみようと思い、いろいろ試してみました。

そこで連想配列か配列か、どちらを使えば効率的に課題をクリアできるか考えたので、その過程をまとめます。

環境

Node.js(v20.11.0)

問題

  • 次のような連想配列がある
[
  { key: 'A', date: '2023/05/01', regiDate: '2023/04/25' },
  { key: 'B', date: '2023/05/02', regiDate: '2023/04/26' },
  { key: 'C', date: '2023/05/03', regiDate: '2023/04/27' },
  { key: 'A', date: '2023/05/04', regiDate: '2023/04/28' },
  { key: 'D', date: '2023/05/05', regiDate: '2023/04/29' },
  { key: 'B', date: '2023/05/02', regiDate: '2023/04/30' },
  { key: 'E', date: '2023/05/07', regiDate: '2023/05/01' },
  { key: 'D', date: '2023/05/08', regiDate: '2023/05/02' },
  { key: 'C', date: '2023/05/09', regiDate: '2023/05/03' },
  { key: 'A', date: '2023/05/04', regiDate: '2023/05/04' }
];
  • この連想配列を次の条件に従い、重複排除するプログラムを作成せよ

【条件】

  • ①同じkeyの値を持つ要素を、一つだけ配列に残す
  • ②dataが最新の要素を残す
  • ③dataが同じ場合は、regiDateが最新の要素を残す

解法

  • forループ内のif文で、配列に含む値を決定する
assignment.js
/*
連想配列を以下の条件に従って重複排除した形に加工するJavaScriptプログラムを作成。

【条件】
1. 同じ "key" の値を持つ要素を、1つだけ配列に残す。
2. "date" が最新の要素を残す。
3. "date" が同じ場合は、"regiDate" が最新の要素を残す。
*/

var data = [
  { key: 'A', date: '2023/05/01', regiDate: '2023/04/25' },
  { key: 'B', date: '2023/05/02', regiDate: '2023/04/26' },
  { key: 'C', date: '2023/05/03', regiDate: '2023/04/27' },
  { key: 'A', date: '2023/05/04', regiDate: '2023/04/28' },
  { key: 'D', date: '2023/05/05', regiDate: '2023/04/29' },
  { key: 'B', date: '2023/05/02', regiDate: '2023/04/30' },
  { key: 'E', date: '2023/05/07', regiDate: '2023/05/01' },
  { key: 'D', date: '2023/05/08', regiDate: '2023/05/02' },
  { key: 'C', date: '2023/05/09', regiDate: '2023/05/03' },
  { key: 'A', date: '2023/05/04', regiDate: '2023/05/04' }
];

var result = {};

for (var i = 0; i < data.length; i++) {
  var item = data[i];
  if (!result[item.key] || item.date > result[item.key].date || (item.date === result[item.key].date && item.regiDate > result[item.key].regiDate)) {
    result[item.key] = item;
  }
}

var output = Object.values(result);
console.log(output);
  • forループを使ってdata配列の各要素(item)を順番の処理します
  • if文では、以下の三つの条件のいずれかが満たされた場合にresultオブジェクトを更新します

1. resultにitem.keyがまだ存在しない場合(つまり、そのキーの要素が初めて見つかった場合)

2. item.dateがresult[item.key].dateより新しい場合(つまり、そのキーの要素で最新の日付が見つかった場合)

3. item.dateとresult[item.key].dateが同じで、かつitem.regiDateがresult[item.key].regiDateより新しい場合(つまり、そのキーの要素で日付が同じでも登録日が最新のものが見つかった場合)


そしてJSに用意されたObject.values()メソッドを使い、resultのすべての値を配列に変換し、outputに格納します。

最初は『resultは配列でよくね?』と思っていましたが、

配列だと要素全体を検索する都合上、要素の数に比例して検索時間が増えるので、パフォーマンス的に厳しいかなと考えました。

一方で連想配列を使えば、プロパティの数に関係なく、特定のキーを持つプロパティに直接アクセスできます。

配列と連想配列(オブジェクト)のパフォーマンスの違い

この両者のパフォーマンスの違いについて、誤解を恐れずもう少し整理しておきます。

配列の場合、配列内の特定の要素を見つけるためには、最悪の場合、配列のすべての要素をチェックする必要があります。

例として先ほどのdata配列を見てみましょう。

var data = [
  { key: 'A', date: '2023/05/01', regiDate: '2023/04/25' },
  { key: 'B', date: '2023/05/02', regiDate: '2023/04/26' },
  { key: 'C', date: '2023/05/03', regiDate: '2023/04/27' },
  { key: 'A', date: '2023/05/04', regiDate: '2023/04/28' },
  { key: 'D', date: '2023/05/05', regiDate: '2023/04/29' },
  { key: 'B', date: '2023/05/02', regiDate: '2023/04/30' },
  { key: 'E', date: '2023/05/07', regiDate: '2023/05/01' },
  { key: 'D', date: '2023/05/08', regiDate: '2023/05/02' },
  { key: 'C', date: '2023/05/09', regiDate: '2023/05/03' },
  { key: 'A', date: '2023/05/04', regiDate: '2023/05/04' }
];

条件に「そのキーの要素が初めて見つかった場合、更新する」というものがありました。

配列の場合、上記の配列からkeyが'E'のオブジェクトを見つけるためには、最初の要素から順に配列を走査していき、最後の要素(keyが'E'のオブジェクト)に到達するまでに時間がかかります。


var data = [
  A: [
    { key: 'A', date: '2023/05/01', regiDate: '2023/04/25' },
    { key: 'A', date: '2023/05/04', regiDate: '2023/04/28' },
    { key: 'A', date: '2023/05/04', regiDate: '2023/05/04' }
  ],
  B: [
    { key: 'B', date: '2023/05/02', regiDate: '2023/04/26' },
    { key: 'B', date: '2023/05/02', regiDate: '2023/04/30' }
  ],
  C: [
    { key: 'C', date: '2023/05/03', regiDate: '2023/04/27' },
    { key: 'C', date: '2023/05/09', regiDate: '2023/05/03' }
  ],
  D: [
    { key: 'D', date: '2023/05/05', regiDate: '2023/04/29' },
    { key: 'D', date: '2023/05/08', regiDate: '2023/05/02' }
  ],
  E: [ { key: 'E', date: '2023/05/07', regiDate: '2023/05/01' } ]
];

一方、連想配列であれば最初から検索することなく、特定のキー(例えば'A'など)に直接アクセスできます。

この点で、要素の数が多くなるほど連想配列を使うメリットがあります。

1
2
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2