連想配列(マップ/ハッシュ/ディクショナリ)の概要

連想配列(マップ/ハッシュ/ディクショナリ)はキーと値の2つのオブジェクトのペアを複数保持し、キーからオブジェクトを取得できるコンテナオブジェクト。連想配列、マップ、ディクショナリなど、言語によって呼び方は違う。

配列が数字を添字とするものに対し、連想配列は任意のオブジェクトを添字にできる。任意といっても添字(キー)にできるオブジェクトには制限のある言語もある。

静的な型の言語では、キーと値はそれぞれすべて同じ型である必要がある。キーと値の型は違っていてもよい。

Java

java.util.Map インターフェースがあり、それを実装したクラスとして、java.util.HashMap, java.util.LinkedHashMap などがある。

java.util.Map のインスタンスを生成したり、要素にアクセスしたりする言語構造ではなく、new 演算子を使ったり、メソッドを使ったりする。

インスタンス生成の例

import java.util.HashMap;

HashMap<String, Integer> map = new HashMap<String, Integer>();
map.put("a", 1);
map.put("b", 2);

空の java.util.Map インスタンスを作るには

Collections.<String, Integer>emptyMap()

要素が1つだけの java.util.Map インスタンスを作るには

Collections.<String, Integer>singletonMap(key, value)

要素を参照するには get を使う。-> キーで値を参照するには

map.get("a");

LRUキャッシュを実装するには java.util.LinkedHashMap が便利。java.util.LinkedHashMap を継承するクラスを作って、removeEldestEntry をオーバーライドすればよい。

なお、java.util.HashMapなどは複数のスレッドから同時に読み書きがあった場合に一貫性を保てなかったり、無限ループになってしまったりするので、synchronized文や、java.util.concurrent.ConcurrentHashMap を使うことを検討すべきである。

Scala

Javaのクラスライブラリでサポートされている java.util.Map インターフェースやその実装クラスのほかに、Scalaのコレクションフレームワークとして scala.collection.Map トレイトがある。

Map には不変(イミュータブル)なものと可変(ミュータブル)なものがあるが、scala.Predef.Mapscala.collection.immutable.Map の別名として定義されているため、なにもimportせずに Map として参照すると不変な Map になる。

Map のインスタンス生成の例

val map = Map("a" -> 1, "b" -> 2);

これは以下のシンタックスシュガー。

val map = scala.collection.immutable.Map.apply(scala.Predef.any2ArrowAssoc("a").`->`(1),
                                               scala.Predef.any2ArrowAssoc("b").`->`(2));

PHP

連想配列が組み込み型として存在する。連想配列のキーに整数を使えば、単純な配列として使うことができ、連想配列と通常の配列の区別がない。

連想配列を生成する例

$map = array('a' => 1, 'b' => 2, );

普通の配列と同様に最後に余計なカンマがあってもなくてもよい。

PHP 5.4からは以下のようにも書ける。

$map = ['a' => 1, 'b' => 2];

この構文でも最後に余計なカンマがあってもよい。

要素を参照するには [] を使う。

$map['a']

キーには以下のような制限がある。

  • 浮動小数点数は整数に切り捨てられてしまう
  • 整数と文字列は区別されない
  • TRUE1 になってしまう
  • FALSE0 になってしまう
  • NULL"" になってしまう
  • 配列やオブジェクトはキーとして使えない

配列 | PHP Manual
配列関係の関数 | PHP Manual

Python

ディクショナリ(辞書)というデータ型がある。

キーにはイミュータブル(不変)なオブジェクトであればなんでもよいので、タプルもキーに使える。

ディクショナリ自体はミュータブル(可変)である。

# ディクショナリの例
dic = {'a': 1, 'b': 2}

# dict関数に2要素のタプルの配列を与えてもよい
dict([('a', 1), ('b', 2)])

# 空のディクショナリ
dic = {}

# 空のディクショナリはdict関数に引数を与えないことでも作れる
dic = dict()

要素を参照するには [] を使う。

dic['a']

Ruby

Hashというハッシュテーブルのクラスが存在する。ハッシュテーブルは {} で表すことができる。

hash = {'a' => 1, 'b' => 2}

Perlと同じく、=> の代わりに , でキーと値を区切ってもよいらしい。

最後に余計なカンマがあっても問題ない。

hash = {
  'a' => 1,
  'b' => 2,
}
p hash
# => {"a"=>1, "b"=>2}

シンボルをキーにする場合、

hash = {:a => 1, :b => 2}

になるが、次のようにも書ける。

hash = {a: 1, b: 2}
# または
hash = {"a": 1, "b": 2}
# 後者の書き方であってもキーは文字列ではなくシンボルになる

要素を参照するには [] を使う。-> キーで値を参照するには

hash['a']

Rubyのハッシュは順序を保存する。キーが追加された順序で列挙される。

class Hash (Ruby 3.0.0 リファレンスマニュアル)

Perl

ハッシュ

Perlではハッシュという。ハッシュの値にはスカラ(文字列、数字、レファレンスなど)しか含められないので、配列やハッシュ自体を値として持たせるには、レファレンスにする必要がある。

ハッシュを入れる変数は名前が % で始まり、要素を参照するには $ で始める。%$ をシジル(sigil)と言う。

ハッシュの変数に要素数が偶数個のリストを代入すると、それがハッシュになる。以下の2つはまったく同じ意味で、どちらもハッシュを %hash に代入している。

my %hash = (a => 1, b => 2);
my %hash = ('a', 1, 'b', 2);

上記のカッコで囲む表記をリストという。

リストの中の =>, とまったく同じ意味で、以下のように書いても差支えない。こんな書き方は普通はしないが。

my %hash = ('a', 1 => 'b', 2);

=> はファットカンマと呼ばれるらしい。

=>, はまったく同じとはいえ、=> の左にシングルクオートやダブルクオートで囲まれていないシンボルのようなものを書くと文字列の扱いになる、という仕様は , にはない。

最後に余計なカンマがあっても問題ない。

my %hash = (
           a => 1,
           b => 2,
          );

ハッシュ %var とスカラ変数 $var は名前の衝突をせず共存できるのだが、普通はコードがわかりづらくなるのでそんなことはしない。

要素を参照するには変数名を $ で始めて、{} を使う。-> キーで値を参照するには

$hash{a}

ハッシュへのレファレンス

リスト表記の () の代わりに {} を使うと、ハッシュへのレファレンスを直接書くことができる。

my $hash = {a => 1, b => 2};

これは以下と同じ。

my %h = (a => 1, b => 2);
my $hash = \%h;

ハッシュへのレファレンスはスカラなので、これ自体を別のハッシュや配列の要素にすることもできる。

レファレンスの実体を取り出すには、%$hash のように頭に % を付ける。

要素を参照するにはいったんハッシュの実体を取り出してからでもいいが、->{} を使うとレファレンスから要素を直接参照することができる。 -> キーで値を参照するには

$hash->{a}

JavaScript

オブジェクトがそのまま連想配列のように使える。JavaScriptにおいてオブジェクトと連想配列は同じで、下の2つは同じオブジェクトを生成する。

map = {a: 1, b: 2}
map = {'a': 1, 'b': 2}

最後に余計なカンマがあっても問題ない。

map = {'a': 1, 'b': 2, }

JSON

JSONフォーマットは、JavaScriptでのオブジェクトの書き方に準ずるがJSONフォーマットのほうがルールが厳しい。

JavaScriptのオブジェクトの表記は、ほぼそのままJSONの表記となるが、少し違う点がある。

  • キーは文字列のみで、必ずダブルクオーテーションで囲む
  • 文字列は " で囲み、 ' で囲むのは禁止
  • 正数であっても先頭に + を付けるのは禁止
  • 0. で始まる浮動小数点数は許されるが、先頭の 0 を省略した表記は禁止
  • 0 で始まる8進数表記や 0x で始まる16進数表記の数値は禁止
  • 文字列の中のエスケープシーケンスとして \0 で始まる8進数表記や \x で始まる16新数表記は禁止で、代わりに \u で始まるUnicodeエスケープを使う。
  • undefinedNaN は禁止

その他にJSONパーサによっての制約もある。

CoffeeScript

map = {a: 1, b: 2}
map = a: 1, b: 2
map =
    a: 1
    b: 2
このサイトは個人メモの集合です。
スポンサーリンク