最終更新日 2024-09-25
~文法メモ~ Map と Set
Map
「連想配列」「map」あるいは、「Dictionary」と言われるもの
コンパイル系言語、スクリプト系言語を問わず、ほとんどの言語で存在する。
従来のJavaScriptえは、Objectで対応してきたが、Mapを利用することで
- Object のキーは「文字列」と「Symbol」ですが、Map では「任意の型」をキーにすることが出来る
- Mapはsize(要素数)を簡単に取得することが出来る。一方、Objectでは、forなどを利用して手動で取得する必要があった。
- Mapだとゴミが無い。Objectはプロトタイプを持つため、既定のキーが最初から存在した。
(但し、これは、Objectでも、 「map = Object.Create(null)」として回避することは可能)
勘違いしてはならないのは、「いつでもMapを使った方がよい」というわけではないということ
- 文字列でないキーが必要か?
- キーと値のペアを時々、追加したり削除したりするか?
- キーが実行時までわからなかったり、キーを直接調べる必要があるか?
- 対象のMapコレクションをイテレートするか?
- 全てが同じ型か?
こういった場合は、既存のObjectではなく、Mapを使ったほうがよいかもしれないサインとなります。
ObjectでもMapでもさして変わらないが、最も簡単な例
let m = new Map();
m.set("foo", "ふ~");
m.set("baa", "ば~");
m.set("ham", "はむ");
m.set("egg", "えっぐ");
hm.debuginfo(m.get("egg")); // えっぐ
文字列以外をキーに出来る
参照系(function型やobject型)では、あくまでも一種の「メモリアドレス的な、レジストリーindex的」なものを キーとします。よって表記が同じかどうかではなく、対象のレジストリーindexが同じかどうかが重要です。
このあたりも他のプログラミング言語の連想配列と同様です。
var myMap = new Map();
var keyString = "文字列";
var keyObj = {},
var keyFunc = function () {};
// 値を設定する
myMap.set(keyString, "'文字列' と関連付けられた値");
myMap.set(keyObj, "keyObj と関連付けられた値");
myMap.set(keyFunc, "keyFunc と関連付けられた値");
hm.debuginfo( myMap.size ); // 3
// 値を取得する
hm.debuginfo( myMap.get(keyString) ); // "'文字列' と関連付けられた値"
hm.debuginfo( myMap.get(keyObj) ); // "keyObj と関連付けられた値"
hm.debuginfo( myMap.get(keyFunc) ); // "keyFunc と関連付けられた値"
hm.debuginfo( myMap.get("文字列") ); // "'文字列' と関連付けられた値"
// keyString === '文字列' であるため
hm.debuginfo( myMap.get({}) ); // undefined, keyObj !== {} であるため
hm.debuginfo( myMap.get(function() {}) ); // undefined, keyFunc !== function () {}
for...ofを利用した反復
.keys(), .values(), .entries()などが用意されています。
デフォルトでは.entries()と同様の動作となります。
let myMap = new Map();
myMap.set(0, "zero");
myMap.set(1, "one");
for (let [key, value] of myMap) {
hm.debuginfo(key + " = " + value);
}
// 0 = zero
// 1 = one
for (let key of myMap.keys()) {
hm.debuginfo(key);
}
// 0
// 1
for (let value of myMap.values()) {
hm.debuginfo(value);
}
// zero
// one
for (let [key, value] of myMap.entries()) {
hm.debuginfo(key + " = " + value);
}
// 0 = zero
// 1 = one
// Mapを順々に処理
myMap.forEach( (value, key) => hm.debuginfo(`${key}=${value}`) );
myMap.set("test", 55);
// 特定のキーを削除
myMap.delete("test");
// 全てのキーと値のペアを削除
myMap.clear();
forEach
.keys(), .values(), .entries()などが用意されています。
デフォルトでは.entries()と同様の動作となります。s
Set
一意な値の「集合」の概念です
コンパイル系言語、スクリプト系言語を問わず、似たようなことが出来る言語も数多くあります。
Mapと類似したものであり、実際しばしばMapの代替としてSetが利用されます。
Setの最も簡単な例
var mySet = new Set();
mySet.add(1);
mySet.add(5);
mySet.add("some text");
var o = {a: 1, b: 2};
mySet.add(o);
mySet.has(1); // true
mySet.has(3); // 3 は集合にないため、false
mySet.has(5); // true
mySet.has(Math.sqrt(25)); // true
mySet.has("Some Text".toLowerCase()); // true
mySet.has(o); // true
mySet.size; // 4
mySet.delete(5); // 集合から 5 を削除
mySet.has(5); // 5 が削除されているため false
mySet.size; // 要素を 1 つ削除しているため 3
for...ofを利用した反復
.keys(), .values(), など、mapと同じ関数が用意されています。
異なる点は、.keys()も.values()も何もメソッドを利用しない状態でも、
全て結果は同じであるということです。
var mySet = new Set();
mySet.add(1);
mySet.add(5);
mySet.add("some text");
mySet.add(() => 3);
// 以下の4つは全部同じとなる。
for (let item of mySet) {
hm.debuginfo(item);
}
for (let item of mySet.keys()) {
hm.debuginfo(item);
}
for (let item of mySet.values()) {
hm.debuginfo(item);
}
// 全部クリア
mySet.clear();
Setの初期化
let mySet = new Set( [1, 5, "some text", () => 3, 100 ] );
というように最初に一気に初期化することが出来ます。