連想配列とキー取り出し

作成日 : 1999-08-27
最終更新日 :

連想配列

データを整理するときに、適切な構造を仮定するとその後の処理が円滑に進む。 連想配列はその一つだ。いろいろなコンピュータ言語に連想配列(辞書、ハッシュ)などの仕組みがある。 JavaScript は連想配列の仕組みが 2 つある。

Map の利用

以下、Map の使い方について説明する。

const rimedo = new Map();
rimedo.set("構造改革", "高度化, 情報化")
rimedo.set("基盤強化", "組織化, 金融")
console.log(rimedo.get("構造改革")) // => 高度化, 情報化
console.log(rimedo.get("基盤強化")) // => 組織化, 金融
	

Map(developer.mozilla.org)

連想配列風の仕掛けの利用

以下、オブジェクトそのものにある連想配列風の仕掛けを利用する方法を述べる。 変数 rimedo に対して、連想配列を適用しよう。まず、次のような初期化が考えられる。

let rimedo = new Array();
rimedo["構造改革"] = "高度化, 情報化"
rimedo["基盤強化"] = "組織化, 金融"
console.log(rimedo["構造改革"]) // => 高度化, 情報化
console.log(rimedo["基盤強化"]) // => 組織化, 金融
	

初期化の工夫

先の方法では変数 rimedo の宣言と初期代入が分かれていた。次の構文を使えばこれらを同時にできる。 Array というオブジェクトが明示的に出てきていないことに注意。なお、 当初は var 宣言を使っていたが、これを const 宣言に変更した。

    const rimedo2 = { "構造改革" : "高度化, 情報化", "基盤強化" : "組織化, 金融"};    

結果は当然同じである。

上記の初期化で、変数名を指定するとどうなるか。

const sxlosilo = "構造改革";
const valoro = "高度化, 情報化";
const rimedo3 = { sxlosilo : valoro};
for (const [key, value] of Object.entries(rimedo3)) {
  console.log(`${key}: ${value}`); // sxlosilo: 高度化, 情報化
}

キーは変数展開されない(値は変数展開される)。キーも変数展開されるようにするためには、[] で囲む。

const sxlosilo = "構造改革";
const valoro = "高度化, 情報化";
const rimedo3 = { [sxlosilo] : valoro};
for (const [key, value] of Object.entries(rimedo3)) {
  console.log(`${key}: ${value}`); // 構造改革: 高度化, 情報化
}

キーは数字や文字列以外のオブジェクトも可能である。配列を使った例である。

  const sxlosilo = [0,1,2,3,5,4,4,6,5];
  const valoro = "主よ、人の望みの喜びよ";
  const rimedo4 = { [sxlosilo]: valoro };
  for (const [key, value] of Object.entries(rimedo4)) {
    console.log(`${key}: ${value}`); // 
  }

キーの取り出し

さて、上記で定義した配列 rimedo からここに入っている添字の文字列が欲しいときはどうするのかを考えよう。

perl では keys という関数があり、添字の文字列を配列として返してくることができる。 JavaScript では、keys に相当する、添字の文字列(の配列)を直接返す手段は、 検索あれこれに書いた通り、 Object.keys() という Object 型の静的メソッドが使える。これは、指定されたオブジェクトが持つプロパティのキーの配列を返す。 もちろん、for (variable in array) という構文を使えば逐次文字列を得ることができる。

for (index in rimedo) {
    document.write(`${index}<br />`);
}

JavaScript ができた当初はこれでもよかったが、その後、document.write は非推奨関数となった。 2021-12-19 に見直した結果を載せる。 そこで、document.write で書き出していた文字列を一度 JavaScript の文字列として受け止め、 それを表示することにしよう。詳しい説明は省略する。

<head>
...
<script>
rimedo = new Array();
rimedo["構造改革"] = "高度化,情報化";
rimedo["基盤強化"] = "組織化,金融";
window.addEventListener('load', (event) => {
let s = "";
for (index in rimedo) {
    s += index + "<br />";
}
let d1 = document.getElementById('rimedo');
d1.insertAdjacentHTML('afterend', s);
</script>
...
</head>
<body>
...
<div id="rimedo">
...
</body>

次がその結果である。

値取り出し時の重複削除

連想配列 arr の複数の異なるキーに対して、同じ値をとる場合がある。このとき、 values = Object.values(arr); で得られる配列 values には、同じ値が入っている。 その場合、Array.from(new Set(values)); として一度集合に変換してから再度配列にすると、 重複が削除される。

	let arr = {a:2, b:3, c:2};
	let a = Object.values(c);        // => [2,3,2]
	let b = Array.from(new Set(a));  // => [2,3]

Array.from と Set は ES2015 で追加された。 Set については、集合(セット)で述べている。
これは覚えておいて損のない方法だ(この項、2022-03-22

キーがプロパティに存在しない場合

プログラムを書いていて、オブジェクトのキーがプロパティに存在しない場合に、デフォルトの値を設定するにはどのような方法があるか知りたくなった。 そこで、ChatGPT に質問してみたら答が返ってきた。質問文は省略して以下引用する。(ChatGPT Mar 23 Version)

JavaScriptにおいて、オブジェクトのキーがプロパティに存在しない場合に、デフォルトの値を設定するには、いくつかの方法があります。

1. undefinedチェックを使用する

最も基本的な方法は、undefinedチェックを使用して、キーが存在しない場合にデフォルト値を設定する方法です。 例えば、次のようなオブジェクトがあるとします。

const obj = { name: 'John', age: 30 };

このオブジェクトにキーが存在しない場合に、デフォルト値を設定するには、以下のようにします。

const defaultValue = 'N/A';
const name = obj.name || defaultValue;
const address = obj.address || defaultValue;
console.log(name);     // 'John'
console.log(address);  // 'N/A'

2. オブジェクトのデフォルト値を設定する

ES6からは、オブジェクトのデフォルト値を設定することができます。これを使用すると、キーが存在しない場合にデフォルト値を設定することができます。

const obj = { name: 'John', age: 30 };
const defaultValue = 'N/A';
const { name = defaultValue, address = defaultValue } = obj;
console.log(name);     // 'John'
console.log(address);  // 'N/A'

3. オブジェクトにデフォルト値を設定する

ES2022(ECMAScript 2022)からは、オブジェクトにデフォルト値を設定することができます。 これを使用すると、オブジェクトが生成されたときに、キーが存在しない場合にデフォルト値を設定することができます。

const obj = { name: 'John', age: 30 };
const defaultValue = 'N/A';
const objWithDefaults = new Proxy(obj, {
  get: function(target, name) {
    return name in target ? target[name] : defaultValue;
  }
});
console.log(objWithDefaults.name);     // 'John'
console.log(objWithDefaults.address);  // 'N/A'

上記の例では、Proxyオブジェクトを使用して、キーが存在しない場合にデフォルト値を返す get ハンドラーを作成しています。これにより、オブジェクトにデフォルト値を設定することができます。

結構仕掛けがいるものだ。ちなみに、Ruby では連想配列のことをハッシュと呼ぶが、 Ruby のハッシュでキーが存在しない場合の既定値をあらかじめ設定しておくことができる。

	h = Hash.new(0)
	p h2["foo"] # => 0

まりんきょ学問所JavaScript 手習い > 連想配列とキー取り出し


MARUYAMA Satosi