配列内の重複している要素を取り出す(uniqの逆と良く言われるもの)には色々な方法が
ありますが group_by を使うとこんな感じになります。
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を返すメソッドが見つからないんです。
で、用意するとこう。
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を返してくれればいいのに!
こんな感じで。
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を返すメソッドがある」とか、「良い方法がある」とか、何かあったら教えてください!
よろしくお願いします。