LoginSignup
5
1

More than 1 year has passed since last update.

ElixirでMapのリストを平均化

Last updated at Posted at 2021-07-17

数週間前にElixir言語公式スラックのあるスレッドを眺めて学んだテクニックをご紹介します。

TL;DR

defmodule Mnishiguchi.Collection do
  @doc """
  Averages a list of maps for specified keys.

  ## Examples

      iex> map_list([%{iaq: 123, temp: 28}, %{iaq: 111, temp: 25}], [:iaq])
      %{iaq: 117.0}

  """
  def avg_maps(map_list, keys) when is_list(map_list) and is_list(keys) do
    map_list
    # マップから指定されていないキーを取り除く
    |> Enum.map(fn x -> Map.take(x, keys) end)
    # マップをタプルに変換
    |> Enum.flat_map(&Map.to_list/1)
    # 各キーでグループ分けをする
    |> Enum.group_by(&elem(&1, 0), &elem(&1, 1))
    # 各グルーブの値を平均化する
    |> Map.new(&{elem(&1, 0), Enum.sum(elem(&1, 1)) / length(elem(&1, 1))})
  end
end

このようなデータがあったとします。

data = [
  %{humi: 85, temp: 35, feeling: "hot"},
  %{humi: 47, temp: 25, feeling: "awesome"}
]

平均化したいキーを指定してavg_maps/2を走らせます。

iex> Mnishiguchi.Collection.avg_maps(data, [:humi, :temp])
%{humi: 66.0, temp: 30.0}

インプットされたデータはこんな感じに加工されていきます。

[%{humi: 85, temp: 35}, %{humi: 47, temp: 25}]
[{:humi, 85}, {:temp, 35}, {:humi, 47}, {:temp, 25}]
%{humi: [85, 47], temp: [35, 25]}
%{humi: 66.0, temp: 30.0}

Wrapping up :lgtm::lgtm::lgtm::lgtm:

5
1
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
5
1