18
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Elixirのコレクションとマップについて

Posted at

この記事の目的

個人的にコレクションとマップがわからなくなったので、備忘を兼ねて。

Elixirにおけるimmutable特性について

Elixirではデータがimmutableなので、変数の値を変更できない。
値を変更しようとした際は、変数のコピーを作成する。
変数のコピーを作成した場合、データ型によってメモリ効率の善し悪しがある。

リスト

リストはheadとtailによる連結リストのデータ構造となっている。
連結リストなので、要素の順番が存在する。
要素の追加・削除を行う操作に適している。

iex> [ head | tail ] = [1 , 2, 3]
[1, 2, 3]
iex> head
1

リストの操作

リストの操作は

  • 要素の参照
  • 要素の個数を参照
  • リストの要素を操作

が出来る。リストの要素を操作する場合、リストの先頭または末尾に値を追加(削除、変更)を行う。
いずれの場合も、コピー元のデータが格納されているメモリを再利用して要素の操作を行うため、メモリ上の無駄は少ない。

要素を参照

リストの要素を参照する場合は、Enumモジュールのat/2関数を使う。要素のインデックスは0から始まる。

iex> list = [1, 2, 3]
[1, 2, 3]
iex)> Enum.at(list, 0)
1
iex> Enum.at(list, 2)
3

要素の個数を参照

リストにおける要素の個数を参照する場合は、length/1関数を使う。リストの要素を末尾までカウントするため、処理は低速となる。

iex> list = [1, 2, 3]
[1, 2, 3]
iex> length(list)
3

先頭に要素を追加

リストは連結リストなので、先頭から順にデータを追っていく。
そのため、先頭に値を追加する場合は高速で実行できる。

iex> list = [1, 2, 3]
[1, 2, 3]
iex> list = [0 | list]
[0, 1, 2, 3]

末尾に要素を追加

リストは、末尾に値を追加する場合は低速になる。

iex> list = [1, 2, 3]
[1, 2, 3]
iex> list ++ [4]
[1, 2, 3, 4]

タプル

タプルはインデックスを利用してメモリ上にデータを隣接して保持するデータ型。
中括弧{}を使って表現する

iex> tuple1 = {"hoge", "foo", "bar", 1}
iex> tuple2 = {1, :a, "boo"}

タプルの操作

タプルはメモリ上にデータが隣接されたデータ型のため、

  • 要素の個数が固定されている
    • 要素の追加・削除ができない
    • 要素を変更すると全ての要素がコピーされため、メモリ上の無駄が発生する
    • 要素を取得、または要素の個数を取得する操作が高速
  • 要素の順番が存在する
    • 要素を取得する際はインデックスを用いる

という性質がある。

要素を取得

タプルから要素を取得する場合はインデックスを用いて、elem/1関数を使う。高速で実行できる。

iex> tuple = {"hoge", "foo", "bar", 1}
{"hoge", "foo", "bar", 1}
iex> elem(tuple, 1)
"foo"

要素の個数を取得

タプルから要素の個数を取得する場合はtuple_size/1関数を使う。高速で実行できる。

iex> tuple = {"hoge", "foo", "bar", 1}
{"hoge", "foo", "bar", 1}
iex> tuple_size(tuple)
4

要素を変更

以下の"hoge"、"bar"の要素は元の変数でメモリに保持していたものではなく、コピーされた結果新しくメモリに格納されたデータとなる。

iex> tuple = {"hoge", "foo", "bar", 1}
{"hoge", "foo", "bar", 1}
iex> tuple = {"hoge", 2, "bar", 3}
{"hoge", 2, "bar", 3}

キーワードリスト

キーワードリストは

  • {key, value}の形のタプルを要素にしたリスト
    • keyのデータ型はアトムでなくてはならない
    • 同一keyが複数存在することが可能
  • リストなので要素の順序が存在する
iex> keyword_list = [{:a, 1}, {:b, 2}] # キーワードリスト
[a: 1, b: 2]
iex> keyword_list = [a: 1, b: 2]       # 要素を中括弧{}無しの key: value で記述可能
[a: 1, b: 2]
iex)> keyword_list = [{:a, 1}, {:b, 2, :c, 3}] # キーワードリストではない
[{:a, 1}, {:b, 2, :c, 3}] 

キーワードリストの操作

キーワードリストはkey:valueの特性と、リストの特性を持っているため、

  • keyを用いてvalueを参照可能
    • 同一keyが複数存在する場合は、より先頭に近い要素のvalueを参照
  • リストの先頭・末尾に要素として{key, value}の形のタプルを追加・削除可能

となる。

要素(value)を参照

要素(value)にはkeyを用いて参照できる。参照する場合はアトムで指定する。

iex> keyword_list = [{:a, 1}, {:b, 2}]       
[a: 1, b: 2]
iex> keyword_list[:a]
1

要素の個数を参照

リストと同様、要素の個数を参照する場合は、length/1関数を使う。

iex> keyword_list = [{:a, 1}, {:b, 2}]       
[a: 1, b: 2]
iex> length(keyword_list)
2

先頭に要素を追加

リスト同様、++/2関数を使って要素を追加する。

iex> keyword_list = [{:a, 1}, {:b, 2}]       
[a: 1, b: 2]
iex> keyword_list = [a: 0] ++ [{:a, 1}, {:b, 2}] # 表記が異なっていても追加可能
[a: 0, a: 1, b: 2]

末尾に要素を追加

リスト同様、末尾に値を追加する場合は低速になる。

iex> keyword_list = [{:a, 1}, {:b, 2}]       
[a: 1, b: 2]
iex> keyword_list = [{:a, 1}, {:b, 2}] ++ [c: 3] # 表記が異なっていても追加可能
[a: 1, b: 2, c: 3]

マップ

マップは、「キー:値」のセットのデータ型。
キーを使って値を参照するが、順序が存在しない。

iex> map = %{ name: "Dave", likes: "Programming", where: "Dallas" }
%{likes: "Programming", name: "Dave", where: "Dallas"}

マップの操作と更新

マップの操作にはMap APIを用いる。

マップのキーを全て参照

iex> map = %{ name: "Dave", likes: "Programming", where: "Dallas" }
%{likes: "Programming", name: "Dave", where: "Dallas"}
iex> Map.keys map
[:likes, :name, :where]

マップの値を全て参照

iex> Map.values map
["Programming", "Dave", "Dallas"]

マップのキーから値を参照

マップが入れ子になっている場合はget_in関数が有効

iex> map[:name]
"Dave"
iex> map.name
"Dave"
iex> get_in(map, [:name])
"Dave"
iex> Map.get(map, :name)  
"Dave"

マップに「キー:値」を追加

iex> Map.put map, :also_likes, "Ruby"
%{also_likes: "Ruby", likes: "Programming", name: "Dave", where: "Dallas"}

マップの更新

iex> map = %{ map | name: "Jane" }
%{likes: "Programming", name: "Jane", where: "Dallas"}

マップから「キー:値」を削除

iex> Map.drop map, [:where, :likes]
%{name: "Dave"}

マップから「キー:値」を取り出して新しいマップを作成する

iex> { value, updated_map} = Map.pop map, :where         
{"Dallas", %{likes: "Programming", name: "Dave"}}
iex> updated_map                                
%{likes: "Programming", name: "Dave"}

参考

18
6
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?