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

> Array#uniq があります。

Array#uniqはUnixのuniqコマンドとは違う挙動をするので注意!

> 5> Hash.new(0).tap{|cnt| ary.each{|e| cnt[e]+=1 }} # => {1=>3, 2=>4, 3=>3}
> 6> ary.count(2)                                    # => 4
> 
> 1〜4 はわかりましたが、5,6 で躓きました。
> tap に秘密がありそう。

Object#tapはレシーバにブロックを作用させて自分自身を返すだけのメソッドです。

  class Object
    def tap
      yield(self)
      self
    end
  end


以下をどうぞ。

http://d.hatena.ne.jp/rubikitch/20080502/tap
http://d.hatena.ne.jp/rubikitch/20080506/1210018999


Enumerable#countは引数で指定された要素を数えます。
ブロックで指定した条件を満たす要素を数えることもできます。
(リファレンスマニュアルにはまだ書いてないが)引数なしで使ったら要素数を返すので、
配列に適用したらArray#lengthと同じ効果です。

--- count(item)             -> Integer
--- count {| obj | block }  -> Integer

Returns the number of items in enum for which equals to item.
If a block is given, counts the number of elements yielding a
true value.

   ary = [1, 2, 4, 2]
   ary.count(2)          # => 2
   ary.count{|x|x%2==0}  # => 3


> http://www.ruby-lang.org/ja/man にもまだ tap, group_by 共に
> # 載っていない様ですね。

新しいリファレンスマニュアル…通称「るりま」をどうぞ。
http://doc.loveruby.net/wiki/

http://d.hatena.ne.jp/rubikitch/20080508/ruby187
にRuby 1.8.7で使えるメソッドを実例とともにまとめています。

>  ary が配列の配列だったときに
>  ary.group_by{|e| e[1] }  
> 見たいにできるのですよね?

もちろん。
配列の配列のときは以下のように多重代入式ブロック引数を使うほうが読みやすくなるでしょう。
http://d.hatena.ne.jp/rubikitch/20080302/1204464916 をどうぞ。

ary = [ [1,2], [6,3], [1,8], [7,9] ]
ary.group_by {|a| a[0] + a[1] }
# => {3=>[[1, 2]], 9=>[[6, 3], [1, 8]], 16=>[[7, 9]]}
ary.group_by {|a,b| a + b }   # ブロック引数の代入は多重代入のルールで
# => {3=>[[1, 2]], 9=>[[6, 3], [1, 8]], 16=>[[7, 9]]}
ary.group_by {|a,b| a * b }
# => {2=>[[1, 2]], 18=>[[6, 3]], 8=>[[1, 8]], 63=>[[7, 9]]}

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