コレクションのまとめ
今まで試してみたコレクション系は以下になる。
- リスト
- 連続した値の集合(コンスセル)
- ランダムアクセスには向かない
- タプルなどを複数持たせる場合等に使用(おそらくは)
- タプル
- 連続した値の集合(メモリ上で連続)
- ランダムアクセスに強い
- 関数の戻り値などで使用(おそらくは)
- キーワードリスト
- keyとvalueのペア
- タプルをリストでまとめる
- コマンドラインやオプションの設定などで使う(おそらくは)
- keyとvalueのペア
さて、ではマップとはなんだろうか。
マップの使い方
ずばりこういうフォーマットになってる。
1 2 |
%{ key => value, key => value, key => value } |
%
って付くとなんだかPerlみたいだよね。perlだと連想配列の記号は%
を使い、
1 2 3 4 5 6 |
%person = ( Name => "Ogaaaan", Age => 1024, Tel => "0120-444-444" ); |
みたいにして使うし、elixirのマップも似たようなものなのかな?と思う。
具体的な使い方を見てみる。
1 2 3 |
iex> status = %{:name => "ogaaaan", :age => 1024, :tel => "0120-444-444"} %{age: 1024, name: "ogaaaan", tel: "0120-444-444"} |
普通に連想配列として使える。
次は呼び出してみる。
1 2 3 |
iex> status[:name] "ogaaaan" |
全く問題ない。
ちなみにkeyは別にアトムじゃなくても大丈夫。文字列でもタプルでも行けてしまう。
1 2 3 |
iex> status2 = %{ {:emotion, :bad} => "dangerous", {:emotion, :good} => "safe" } %{{:emotion, :bad} => "dangerous", {:emotion, :good} => "safe"} |
この場合、キーがタプルになってるので、『感情が悪いとき → 危険』、『感情が良いとき → 安全』みたいな感じで指定してみた。
呼び出しは同じ様に、
1 2 3 |
iex> status2[{:emotion,:bad}] "dangerous" |
でOKらしい。なるほど。ある意味わかりやすい。
ソースコードを一通り終えて、別の人がメンテナンスするなんて時には、キーをタプルにしておくと、コメントいらずかな。
コードリーディングという意味でも良いのかもしれない。
マップ内のkeyは同じ型でなくても大丈夫なので、文字列、タプル、アトムでもなんでも混在できる。
1 2 3 |
iex> status3 = %{ "A" => "b", {:john, :doe} => "me", :whois => "ogaaaan" } %{:whois => "ogaaaan", {:john, :doe} => "me", "A" => "b"} |
メモリへの格納時には最適化されるらしく、順番が変わることもあるね。
連想配列にとって順序というのは無視して良いものなので、マップも気にしないほうが良いだろう。
keyには式を指定しても、ちゃんと評価される。
文字列を小文字にする関数をつかってkeyを設定してみる。
1 2 3 |
iex> status4 = %{ String.downcase("MY NAME IS") => "Ogaaaan"} %{"my name is" => "Ogaaaan"} |
マップの使い方
Perlの連想配列と比較してみたが、回答はこうだ。
elixirのマップはperlの連想配列と同意
なるほど。連想配列を使いたかったらマップを使え、ということだ。
そしてちょっと待て。であれば、キーワードリストって何のためにあるの?
キーワードリストとの違い
冒頭に書いたように、キーワードリストの特徴はこうだ。
- キーワードリスト
- keyとvalueのペア
- タプルをリストでまとめる
- コマンドラインやオプションの設定などで使う(おそらくは)
- keyとvalueのペア
そしてマップの特徴はこうだ。
- マップ
- keyとvalueのペア
- keyはタプル、文字列、アトムなど混在OK
- Perlの連想配列と同じ様に使える
- keyとvalueのペア
何が違うのか、調べてみた。すると、こんなことがわかった。
- キーワードリストは同じkeyを複数持てる
- マップは同じkeyは複数持てない
試してみる。まずはキーワードリスト。
1 2 3 |
iex> kwl = [ {"A", 100}, {"A", 200}, {"A", 300 } ] [{"A", 100}, {"A", 200}, {"A", 300}] |
マジだった。おそらく{}
ブレイス内のスコープなんだろうな。
マップではどうだろうか。
1 2 3 |
iex> mp = %{ "A" => 100, "A" => 200, "A" => 300 } %{"A" => 300} |
おぉ、別にエラーというわけじゃなく、順次評価していった結果になるわけだ。なるほど理解。
やっぱりここでは、{}
ブレイス内で一つのスコープと言うように認識しておくと良いのかもね。
結論
コレクション系のまとめは、つまりこうなる。
- リスト
- 連続した値の集合(コンスセル)
- ランダムアクセスには向かない
- タプルなどを複数持たせる場合等に使用(おそらくは)
- タプル
- 連続した値の集合(メモリ上で連続)
- ランダムアクセスに強い
- 関数の戻り値などで使用(おそらくは)
- キーワードリスト
- keyとvalueのペア
- タプルをリストでまとめる
- keyは重複できる
- コマンドラインやオプションの設定などで使う(おそらくは)
- keyとvalueのペア
- マップ
- keyとvalueのペア
- keyはタプル、文字列、アトムなど混在OK
- keyは重複してるとまとめられる(上書き)
- Perlの連想配列と同じ様に使える
- keyとvalueのペア
おわり
次回は変数のスコープとかやってみようかな。