LoginSignup
3
5

More than 5 years have passed since last update.

Rubyでselfを返すメソッドってあったっけ?

Posted at

配列内の重複している要素を取り出す(uniqの逆と良く言われるもの)には色々な方法が
ありますが group_by を使うとこんな感じになります。

duplicate.rb
class Array
  def duplicate
    self.group_by{ |e| e }.reject{ |k, v| v.one? }.keys
  end
end

ary = [*0.step(8, 2)] + [*0..9]   # => [0, 2, 4, 6, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
ary.duplicate                     # => [0, 2, 4, 6, 8]

ちょっとイヤだと思うのが group_by のブロック部 { |e| e } のところ。
個人的にはself.group_by(&:self).reject{ |k, v| v.one? }.keysな感じで書きたい。
でも、このselfメソッドのようにselfを返すメソッドが見つからないんです。

で、用意するとこう。

dupli.rb
class Object 
  def self ; self end 
end

class Array
  def dupli
    self.group_by(&:self).reject{ |k, v| v.one? }.keys
  end
end

ary = [*0.step(8, 2)] + [*0..9]   # => [0, 2, 4, 6, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
ary.dupli                         # => [0, 2, 4, 6, 8]

selfを返すメソッドといえば、思い付くのが「tap」なんですけど「tap」はブロックがないと
localJumpError: no block givenなんで普通に使う時は1.tap{} # => 1でも構わない
のですが、上記のselfメソッドのように使う時にはブロックを書くと syntax error になります。

なんでブロック必須なんだろ??ブロックがない時はselfを返してくれればいいのに!
こんな感じで。

dupli.rb
class Object
  def tap
    block_given? ? super : self
  end
end

class Array
  def dupli 
    self.group_by(&:tap).reject{ |k, v| v.one? }.keys
  end
end

ary = [*0.step(8, 2)] + [*0..9]   # => [0, 2, 4, 6, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
ary.dupli                         # => [0, 2, 4, 6, 8]

今のところ group_by くらいでしか使い道は思い付かないんですけど group_by は結構好きなので
selfを返すメソッドはやっぱり欲しいなぁ。

ただ知らなかっただけは恥ずかしいので
「selfを返すメソッドがある」とか、「良い方法がある」とか、何かあったら教えてください!
よろしくお願いします。

3
5
5

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
3
5