1_8.基本問題2 - ohr486/ErlangElixirFestHandsOn GitHub Wiki
1_8.基本問題2
基本問題1の関数化
毎回、コンソールで処理を入力するのは手間ですので、以下の様に関数化します。
defmodule モジュール do
def 関数(引数) do
関数の処理
end
end
基本問題1をlib/basic.ex
の関数q1
として以下の様に実装します。
defmodule Basic do
〜略〜
def q1 do
# ファイルの読み込み
data = File.stream!("data.json")
# JSON文字列をmapに変換
map_data = Enum.map(data, fn d -> Poison.decode!(d) end)
# age <= 20 でフィルタリング
filter_data = Enum.filter(map_data, fn d -> d["age"] <= 20 end)
# 件数を取得
Enum.count(filter_data)
end
end
elixirはパイプ演算子(|>
)を使って、関数の結果を次の関数の第一引数として受け渡せます。
r1 = func1(arg1, arg2)
r2 = func2(r1, arg3)
は
arg1
|> func1(arg2)
|> func2(arg3)
とかけます。
関数q1
をパイプ演算子を使って記述すると
def q1 do
"data.json"
|> File.stream!
|> Enum.map(fn d -> Poison.decode!(d) end)
|> Enum.filter(fn d -> d["age"] <= 20 end)
|> Enum.count
end
とかけます。
Streamを使った実装(遅延処理)
Enum.map
をStream.map
に差し替えれば遅延処理になります。
def q2_1 do
"data.json"
|> File.stream!
|> Stream.map(fn d -> Poison.decode!(d) end)
|> Stream.filter(fn d -> d["age"] <= 20 end)
|> Enum.count
end
Flowを使った実装(並列処理)
Flowを使った並列化は
データソース
|> Flow.from_enumerable # これを追加
|> Flow.xxx # Enum/Stream -> Flow に変更
|> Flow.partition # これを追加
|> xxx
とすることで並列化できます。
def q2_2 do
"data.json"
|> File.stream!
|> Flow.from_enumerable
|> Flow.map(fn d -> Poison.decode!(d) end)
|> Flow.partition
|> Flow.filter(fn d -> d["age"] <= 20 end)
|> Enum.count
end
Flowはライブラリとなっていますので、mix.exsに下記のように記載を行い mix deps.get にてライブラリを取得してください。
defp deps do
[
{:poison, "~> 3.1"},
{:flow, "~> 0.13"}
]
end