LoginSignup
13
0

More than 1 year has passed since last update.

今日のElixirSchoolメモ3「Enum」

Posted at

Elixir Schoolの学習メモです

Enumモジュールとは?

Enumモジュールは列挙型を操作するためのおよそ70個以上の関数を含んでいる。
タプルを除く全てのコレクションを列挙できる。

all?/2

コレクションの要素に対して適用する関数を渡す。
コレクションの全体がtrueと評価されなければならず、そうでなければfalseが返される。

iex(19)> Enum.all?(["foo", "bar", "hello"], fn(s) -> String.length(s) == 3 end)
false
iex(20)> Enum.all?(["foo", "bar", "hello"], fn(s) -> String.length(s) > 1 end)
true

any?

少なくとも1つの要素がtrueと評価された場合にtrueを返す。

iex(21)> Enum.any?(["foo", "bar", "hello"], fn(s) -> String.length(s) == 5 end)
true

chunk_every

コレクションを小さなグループに分割できる。

iex(22)> Enum.chunk_every([1, 2, 3, 4, 5, 6], 2)
[[1, 2], [3, 4], [5, 6]]

chunk_by

要素数ではない他の何かでコレクションを分類したい場合に使う。

iex(23)> Enum.chunk_by(["one", "two", "three", "four", "five"], fn(x) -> String.length(x) end)
[["one", "two"], ["three"], ["four", "five"]]
iex(24)> Enum.chunk_by(["one", "two", "three", "four", "five", "six", "seven"], fn(x) -> String.length(x) end)
[["one", "two"], ["three"], ["four", "five"], ["six"], ["seven"]]

map_every

n毎のアイテムに対して何かの処理をしたい場合に使う。
これは最初の要素は必ず処理される。

iex(25)> Enum.map_every([1,2,3,4,5,6,7,8], 3, fn x -> x + 1000 end)
[1001, 2, 3, 1004, 5, 6, 1007, 8]

each

新しい値を生成することなく、コレクションを反復する場合に使う。

iex(26)> Enum.each(["one", "two", "three"], fn(s) -> IO.puts(s) end)
one
two
three
:ok

map

関数を各要素に適用して新しいコレクションを生み出すときに使う。

iex(27)> Enum.map([0,1,2,3], fn(x) -> x-1 end)
[-1, 0, 1, 2]

minmax

第②引数には、コレクションが空だった場合の最小値or最大値が設定できる。

iex(28)> Enum.max([5,3,0,0,-1])
5
iex(29)> Enum.max([], fn -> :bar end)
:bar

filter

iex(30)> Enum.filter([1,2,3,4], fn(x) -> rem(x,2) == 0 end)
[2, 4]

reduce

要素を1つの値に畳み込む。
任意のアキュムレータを渡すことができる。アキュムレータが指定されない場合はコレクションの最初の要素が用いられる。

iex(32)> Enum.reduce([1,2,3], 10, fn(x, acc) -> x + acc end)
16
iex(33)> Enum.reduce([1,2,3], fn(x, acc) -> x + acc end)
6
iex(34)> Enum.reduce(["a","b","c"], "1", fn(x, acc) -> x <> acc end)
"cba1"

sort

sort/1はソートの順序を決めるためにErlangのTerm優先順位を使う。
https://www.erlang.org/doc/reference_manual/expressions.html#term-comparisons

iex(35)> Enum.sort([5, 6, 1, 3, -1, 4])
[-1, 1, 3, 4, 5, 6]
iex(36)> Enum.sort([:foo, "bar", Enum, -1, 4])
[-1, 4, Enum, :foo, "bar"]

sort/2では順序を決める関数を渡すことができる。

iex(39)> Enum.sort([%{:val => 4}, %{:val => 1}], fn(x, y) -> x[:val] > y[:val] end)
[%{val: 4}, %{val: 1}]

:descや:ascを渡すこともできる。

iex(38)> Enum.sort([5, 6, 1, 3, -1, 4], :desc)
[6, 5, 4, 3, 1, -1]

uniquniq_by

iex(41)> Enum.uniq([1, 2, 3, 2, 1, 1, 1, 1, 1])
[1, 2, 3]

uniq_byはユニークかどうかを比較する関数を渡すことができる。

iex(42)> Enum.uniq_by([%{x: 1, y: 1}, %{x: 2, y: 1}, %{x: 3, y: 3}], fn coord -> coord.y end)
[%{x: 1, y: 1}, %{x: 3, y: 3}]

キャプチャ演算子(&)を使用したEnum

Enumモジュール内の多くの関数は、渡されるEnum型のオブジェクトを処理するための引数として無名関数を取る。
これらの無名関数は、多くの場合、キャプチャ演算子(&)を使用して省略形で記述されることが多い。

Enum.map([1, 2, 3], fn number -> number + 3 end)

上記は、下記のように実装できる。
数値のリスト([1, 2, 3])の各要素をキャプチャし、マッピング関数を通過するときに各要素を&1に割り当てる。

Enum.map([1, 2, 3], &(&1 + 3))

無名関数を変数に割り当て、Enum.map/2関数から呼び出すこともできる。

plus_three = &(&1 + 3)
Enum.map([1, 2, 3], plus_three)

名前つき関数でのキャプチャ演算子の使用

defmodule Adding do
  def plus_three(number), do: number + 3
end

Enum.map([1, 2, 3], &Adding.plus_three(&1))

変数を明示的にキャプチャせずに、名前つき関数を直接呼び出すことができる。

Enum.map([1, 2, 3], &Adding.plus_three/1)
13
0
0

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
13
0