Ruby 2.2 で追加されたメソッドまとめをみてた。
New Methods in Ruby 2.2
Enumerable#slice_when
のユースケースでEnumerable内での各要素出現数をカウントするのがステキだったので、2.2以前も含めてどう書けるパターンあるんだっけ?をメモ。
カウント対象のArrayを生成
labels = ["aaa", "bbb", "ccc"]
ary = Array.new(20) { labels.sample }
puts ary.join ", "
# bbb, aaa, bbb, bbb, bbb, aaa, ccc, aaa, aaa, bbb, ccc, ccc, bbb, bbb, aaa, aaa, ccc, bbb, aaa, aaa
2.2以前
Enumerable#inject
を利用
r1 = ary.inject(Hash.new(0)) {|h, e| h.tap {|h| h[e] += 1} }
puts r1
# {"bbb"=>8, "aaa"=>8, "ccc"=>4}
2.2から
Enumerable#slice_when
を利用
あえて出力結果を Hash に寄せてみる。
r2 = ary.sort.slice_when(&:!=).map {|x| [x.first, x.size] }
puts Hash[r2]
# {"aaa"=>8, "bbb"=>8, "ccc"=>4}
Enumerable#group_by
+ Object#itself
でもイケるな
r3 = ary.group_by(&:itself).map {|k, v| [k, v.size] }
puts Hash[r3]
# {"bbb"=>8, "aaa"=>8, "ccc"=>4}
メモ
-
Enumerable#inject
は副作用ベースな書き方なのでいつも一瞬「うっ」ってなってる -
Enumerable#slice_when
は#sort
しないといけないね - 要素数が大きくなった場合に計算量とメモリ使用量の観点で効率的なのはどれだろう?
- 富豪的な実装でもいいから簡単に書きたい時もあるよね、使い分けたい
コード全体
labels = ["aaa", "bbb", "ccc"]
ary = Array.new(20) { labels.sample }
puts ary.join ", "
r1 = ary.inject(Hash.new(0)) {|h, e| h.tap {|h| h[e] += 1} }
puts r1
r2 = ary.sort.slice_when(&:!=).map {|x| [x.first, x.size] }
puts Hash[r2]
r3 = ary.group_by(&:itself).map {|k, v| [k, v.size] }
puts Hash[r3]