10
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【TIPS】Enum.frequenciesと同じリスト集計処理を自前で実装する

Last updated at Posted at 2024-12-10

この記事は、Elixir Advent Calendar 2024 シリーズ9 の10日目です


【本コラムは、3分で読め、3分で試せます】

piacere です、ご覧いただいてありがとございます :bow:

Enum.frequencies は、Elixir 1.10で追加された、リスト中の値の発生頻度を数えてくれる便利な関数で、利用頻度もそれなりに高いのですが、Elixir 1.9までは存在していなかったので、自前で作る必要があったので、作り方を解説します

Enum.frequencies(["abc", "abc", "xyz", "abc", "def", "xyz"])
%{"abc" => 3, "def" => 1, "xyz" => 2}

Enum.frequencies([
  %{"a" => "abc"}, 
  %{"b" => "abc"}, 
  %{"a" => "xyz"}, 
  %{"a" => "abc"}, 
  %{"a" => "def"}, 
  %{"a" => "xyz"}
])
%{
  %{"a" => "abc"} => 2,
  %{"a" => "def"} => 1,
  %{"a" => "xyz"} => 2,
  %{"b" => "abc"} => 1
}

そんな集計処理を叶えてくれるパーツが、これまた便利な Map.update です

単品のMap.updateは、第1引数にあるマップに対し、第2引数のキーで、第3引数の初期値と第4引数の関数で計算した値をマップに追加してくれます

Map.update(%{}, "a", 1, fn x -> x + 1 end)
%{"a" => 1}

この特性を、パイプで使うと、下記のようなマップの更新処理が実現できます

%{}
|> Map.update("a", 1, fn x -> x + 1 end)
|> Map.update("b", 1, fn x -> x + 1 end)
|> Map.update("a", 1, fn x -> x + 1 end)
%{"a" => 2, "b" => 1}

同じようなことをEnum.reduceで行うと、リストに対する集計を行い、集計結果をマップとして残すことが可能です

datas = ["abc", "abc", "xyz", "abc", "def", "xyz"]

datas
|> Enum.reduce(%{}, & Map.update(&2, &1, 1, fn x -> x + 1 end))
%{"abc" => 3, "def" => 1, "xyz" => 2}

こうしたEnum.reduceによる集計処理が自由に書けるようになると、Elixirをはじめとする関数型言語に対する「苦手意識」のようなものが無くなり、関数型言語以外を触りたいとは思えなくなるので、ぜひマスターしてみてください

p.s.このコラムが、面白かったり、役に立ったら…

image.png にて、どうぞ応援よろしくお願いします :bow:

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?