patorashのブログ

方向性はまだない

配列に同じ要素が何個あるかを数える

先日、会社のチャットワークでそういう話題が出て、いろんな方法があることを知った。

1. array.count(item)

l = [1,2,2,1,3]
l.uniq.map{|item| [item, l.count(item)]}.to_h

配列の変数のcountメソッドの引数に値を渡したら同じ値をカウントしてくれるっていうのは知らなかった。

2. array.group_by(&:itself)を使ってからmap

l = [1,2,2,1,3]
l.group_by(&:itself).map{ |k, v| [k, v.size] }.to_h

group_byをしているほうがイケてる感じ。しかしto_hがなんかダサい…。これをなんとかしたい…。

3. array.group_by後にtransform_values

l = [1,2,2,1,3]
l.group_by(&:itself).transform_values(&:size)

うおお、あったー!transform_valuesメソッド!Hashのvalueを更新するメソッド。 メソッド名はちと長いけれど、これが一番イケてる。ブロック書かずに済んだし。

itselfメソッドも知らなかったので収穫であった。

こういう話題が社内で流れてくると楽しいですね。

追記(2022-04-22)

Ruby 2.7でEnumerable#tallyメソッドが追加されています。これを使うと同じことができます。めちゃくちゃ短くてシンプル!

docs.ruby-lang.org

l = [1,2,2,1,3]
l.tally # => {1 => 2, 2 => 2, 3 => 1}