Elixir-列挙可能

列挙可能なオブジェクトは、列挙できるオブジェクトです。「列挙型」とは、セット/コレクション/カテゴリのメンバーを1つずつ(通常は順番に、通常は名前で)カウントすることを意味します。

Elixirは、列挙型の概念とそれらを操作するためのEnumモジュールを提供します。Enumモジュールの関数は、その名前が示すように、データ構造内の値の列挙に制限されています。列挙可能なデータ構造の例は、リスト、タプル、マップなどです。Enumモジュールは、列挙を処理するための100を少し超える関数を提供します。この章では、いくつかの重要な機能について説明します。

これらの関数はすべて、最初の要素として列挙可能要素を取り、2番目の要素として関数を取り、それらを処理します。機能は以下のとおりです。

すべて?

使用する場合 all?関数の場合、コレクション全体がtrueと評価される必要があります。そうでない場合、falseが返されます。たとえば、リスト内のすべての要素が奇数であるかどうかを確認するには、。

res = Enum.all?([1, 2, 3, 4], fn(s) -> rem(s,2) == 1 end) 
IO.puts(res)

上記のプログラムを実行すると、次の結果が生成されます-

false

これは、このリストのすべての要素が奇数であるとは限らないためです。

どれか?

名前が示すように、コレクションのいずれかの要素がtrueと評価された場合、この関数はtrueを返します。例-

res = Enum.any?([1, 2, 3, 4], fn(s) -> rem(s,2) == 1 end)
IO.puts(res)

上記のプログラムを実行すると、次の結果が生成されます-

true

チャンク

この関数は、コレクションを2番目の引数として指定されたサイズの小さなチャンクに分割します。例-

res = Enum.chunk([1, 2, 3, 4, 5, 6], 2)
IO.puts(res)

上記のプログラムを実行すると、次の結果が生成されます-

[[1, 2], [3, 4], [5, 6]]

新しい値を生成せずにコレクションを反復処理する必要がある場合があります。この場合、 each 関数-

Enum.each(["Hello", "Every", "one"], fn(s) -> IO.puts(s) end)

上記のプログラムを実行すると、次の結果が生成されます-

Hello
Every
one

地図

関数を各アイテムに適用して新しいコレクションを作成するには、map関数を使用します。非常に表現力があり短いため、関数型プログラミングで最も有用な構成の1つです。これを理解するための例を考えてみましょう。リストに格納されている値を2倍にして、新しいリストに格納しますres

res = Enum.map([2, 5, 3, 6], fn(a) -> a*2 end)
IO.puts(res)

上記のプログラムを実行すると、次の結果が生成されます-

[4, 10, 6, 12]

減らす

ザ・ reduce関数は、列挙可能な値を1つの値に減らすのに役立ちます。これを行うために、関数に渡されるオプションのアキュムレータ(この例では5)を提供します。アキュムレータが提供されていない場合は、最初の値が使用されます-

res = Enum.reduce([1, 2, 3, 4], 5, fn(x, accum) -> x + accum end)
IO.puts(res)

上記のプログラムを実行すると、次の結果が生成されます-

15

アキュムレータは、に渡される初期値です。 fn。2回目の呼び出し以降、前の呼び出しから返された値が累積として渡されます。アキュムレータなしでreduceを使用することもできます-

res = Enum.reduce([1, 2, 3, 4], fn(x, accum) -> x + accum end)
IO.puts(res)

上記のプログラムを実行すると、次の結果が生成されます-

10

uniq

uniq関数は、コレクションから重複を削除し、コレクション内の要素のセットのみを返します。例-

res = Enum.uniq([1, 2, 2, 3, 3, 3, 4, 4, 4, 4])
IO.puts(res)

上記のプログラムを実行すると、次の結果が生成されます-

[1, 2, 3, 4]

熱心な評価

Enumモジュールのすべての関数は熱心です。多くの関数は列挙可能を期待し、リストを返します。これは、Enumを使用して複数の操作を実行する場合、結果に到達するまで、各操作が中間リストを生成することを意味します。これを理解するために、次の例を考えてみましょう-

odd? = &(odd? = &(rem(&1, 2) != 0) 
res = 1..100_000 |> Enum.map(&(&1 * 3)) |> Enum.filter(odd?) |> Enum.sum 
IO.puts(res)

上記のプログラムを実行すると、次の結果が生成されます-

7500000000

上記の例には、操作のパイプラインがあります。範囲から始めて、範囲内の各要素に3を掛けます。この最初の操作では、100_000項目のリストが作成されて返されます。次に、リストからすべての奇数要素を保持し、50_000アイテムの新しいリストを生成してから、すべてのエントリを合計します。

ザ・ |> 上記のスニペットで使用されている記号は pipe operator:左側の式から出力を取得し、それを最初の引数として右側の関数呼び出しに渡すだけです。Unixに似ています| オペレーター。その目的は、一連の関数によって変換されるデータの流れを強調することです。

なし pipe 演算子、コードは複雑に見えます-

Enum.sum(Enum.filter(Enum.map(1..100_000, &(&1 * 3)), odd?))

他にも多くの機能がありますが、ここではいくつかの重要な機能についてのみ説明しました。