LoginSignup
2

More than 5 years have passed since last update.

Elixir~Enum総ざらい4回目~

Last updated at Posted at 2019-02-17

Enum.fetch


Enum.fetch([2, 4, 6], 0)
{:ok, 2}

iex> Enum.fetch([2, 4, 6], -3)
{:ok, 2}

iex> Enum.fetch([2, 4, 6], 2)
{:ok, 6}

iex> Enum.fetch([2, 4, 6], 4)
:error
Enum.fetch([2, 4, 6, 8],3)
{:ok, 8}

これは簡単なようです。リストの引数に対して、ゼロから数えてn番目の値があればokとともに返す関数のようです。

Enum.find

Enum.find([2, 4, 6], fn x -> rem(x, 2) == 1 end)
nil

Enum.find([2, 4, 6], 0, fn x -> rem(x, 2) == 1 end)
0

Enum.find([2, 3, 4], fn x -> rem(x, 2) == 1 end)
3

こちらは第一引数のなかから2で割ってあまりが1になるという条件式にあてはまる数値を返すようです。ただ、1番目の式の結果がnil、2番目で0が挿入されていると結果が0になるところがやや引っかかるところです。

Enum.find_index

Enum.find_index([2, 4, 6], fn x -> rem(x, 2) == 1 end)
nil

Enum.find_index([2, 3, 4], fn x -> rem(x, 2) == 1 end)
1

こちらはEnum.findと似ていますが、第一引数のリストのなかから条件式にあてはまる要素の数を返している、、のかな?

Enum.find_value

Enum.find_value([2, 4, 6], fn x -> rem(x, 2) == 1 end)
nil

Enum.find_value([2, 3, 4], fn x -> rem(x, 2) == 1 end)
true

Enum.find_value([1, 2, 3], "no bools!", &is_boolean/1)
"no bools!

こちらも条件式に対して結果を返すもののようですが、条件式にあてはまるものがなければnil、ひとつでもあればtrueを返しているのでしょうか。
3番目の式に関してはわたしの知識では図りかねます。

Enum.flat_map


Enum.flat_map([:a, :b, :c], fn x -> [x, x] end)
[:a, :a, :b, :b, :c, :c]

Enum.flat_map([{1, 3}, {4, 6}], fn {x, y} -> x..y end)
[1, 2, 3, 4, 5, 6]

Enum.flat_map([:a, :b, :c], fn x -> [[x]] end)
[[:a], [:b], [:c]]

こちらはかなりお手上げに近いのですが、最後のendの前の[x,x]、x..y、[[x]]の違いに着目してみると、ある一定の法則が見いだせそうです。

Enum.flat_map_reduce

enumerable = 1..100
 n = 3
 Enum.flat_map_reduce(enumerable, 0, fn x, acc ->
  if acc < n, do: {[x], acc + 1}, else: {:halt, acc}
 end)
{[1, 2, 3], 3}

 Enum.flat_map_reduce(1..5, 0, fn x, acc -> {[[x]], acc + x} end)
{[[1], [2], [3], [4], [5]], 15}

公式ドキュメント からの英文を転載しておきます。

Maps and reduces an enumerable, flattening the given results (only one level deep).

It expects an accumulator and a function that receives each enumerable item, and must return a tuple containing a new enumerable (often a list) with the new accumulator or a tuple with :halt as first element and the accumulator as second.

完全にお手上げです。現時点の知識では全くわかりません。

Enum.group_by

Enum.group_by(~w{ant buffalo cat dingo}, &String.length/1)
%{3 => ["ant", "cat"], 5 => ["dingo"], 7 => ["buffalo"]}

Enum.group_by(~w{ant buffalo cat dingo}, &String.length/1, &String.first/1)
%{3 => ["a", "c"], 5 => ["d"], 7 => ["b"]}

複雑ですが法則性が見えてきます。

最初の式では、それぞれ綴りの文字数ごとにソートして結果を返しています。
2番目の式では、&String.first/1が付与されているので、それぞれの綴りの文字数ごとに最初の一文字を返しているように思えます。

Enum.intersperse

Enum.intersperse([1, 2, 3], 0)
[1, 0, 2, 0, 3]

Enum.intersperse([1], 0)
[1]

Enum.intersperse([], 0)
[]

これは簡単そうです。第一引数のリストに対して、この場合一個ごとにゼロを挿入して、第一引数がひとつか何もない場合はそのまま返しているようです。

雑感

正直この作業は自助努力というかそういう同期で始めたものではないのですが、まだEnumだけで半分以上ある...
もちろんわからないものを図示するのも含めてあとで貴重な教材になるのでしょうが、わからないものをわからないとネットに書くのもなかなかに抵抗があったりします(苦笑

めげずにやるしかないです。
うまずたゆまず、頑張ります。
Kento Mizuno

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
2