From: しん <dezawa / aliadne.net>
Subject: [ruby-list:45065] uniq -c みたいなことはできないか
Date: Mon, 16 Jun 2008 12:28:59 +0900

るびきちです。

> Array にあるデータを 値ごとにまとめて数を数えたいのですが、
> uniq ですと重複をなくすだけのようです。

そうです。
ちなみにクラスは違えどString#squeezeがUnixコマンドのuniq相当です。
Array#squeezeはありません。

s = "122113"
s.squeeze                       # => "1213"

> 今までは cnt=Hash.new(0);ary.each{|a| cnt[a]=cnt[a]+1} などと書いていましたが
> こんなこときっともっと簡単な方法があるに違いない、と思っての質問です。

RUBY_VERSION   # => "1.8.7"
ary = [1, 2, 1, 1, 3, 2, 2, 3, 3, 2]
ary.group_by{|e| e}
# => {1=>[1, 1, 1], 2=>[2, 2, 2, 2], 3=>[3, 3, 3]}
Hash.new(0).tap{|cnt| ary.each{|e| cnt[e]+=1 }} # => {1=>3, 2=>4, 3=>3}
ary.count(2)                                    # => 4

Enumerable#group_byがそれに近いです。
ただし、要素をブロックでグループ分けするだけなので、ハッシュの値は配列になります。
処理の続きがあるならば、

ary.group_by{|e| e}.each_pair do |e, a|
  len = a.length
  # ....
end  

のように続けることができます。

# Hash#mapがあればEnumerable#group_byと組み合わせられるけど…

もうひとつ、Object#tapを使うとメソッドチェーンで書けます。

特定の要素のみを数えるにはEnumerable#countも使えます。

どの方法もRuby 1.8.7が必要です。

--
rubikitch
Blog: http://d.hatena.ne.jp/rubikitch/
Site: http://www.rubyist.net/~rubikitch/