連想配列とキー取り出し

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

連想配列

これからしばらくデータの初期化を中心に調べる。 データを整理するときに、適切な構造を仮定するとその後の処理が円滑に進む。 連想配列はその一つだ。たとえば、次のようにして配列 rimedo の添字に文字列を使うことができる。

		var rimedo["構造改革"] = new Array("高度化", "情報化")
		var rimedo["基盤強化"] = new Array("組織化", "金融")
	

最初このように書いてしまったが、これはいけない。 エラーこそ返さないもの、後の JavaScript の処理が全く行われない。 そこでまず、rimedo が配列であることを宣言しないといけない。 また、配列をわりつけることも問題だ。そこで、配列ではなく、単なるカンマ接続文字列として捉えよう。

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

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

キーの取り出し

perl では keys という関数があり、添字の文字列を配列として返してくることができる。 JavaScript では、keys に相当する、添字の文字列(の配列)を直接返す手段は、 検索あれこれに書いた通り、 Object.keys() というメソッドが使える。これは、指定されたオブジェクトが持つプロパティのキーの配列を返す。 もちろん、for (var 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>

次がその結果である。

初期化の工夫

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

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

結果は当然同じである。

値取り出し時の重複削除

連想配列 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
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/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