如何让自定义Ruby类Foo兼容Enumerable#grep方法?
解决Ruby中自定义类适配Enumerable#grep的问题
你的问题核心在于搞反了Enumerable#grep中===的调用方向:grep执行的是pattern === element,也就是正则(pattern)调用===方法,参数是Foo实例(element),而非你之前写的Foo实例调用===接收正则。因此你实现的Foo#===方法根本不会被触发。
要让Foo实例能被正则通过grep匹配,需要利用Ruby中Regexp#===的特性:当参数不是字符串时,它会尝试调用参数的#=~方法,传入自身作为参数。只要#=~返回非nil值,Regexp#===就会返回true,进而被grep筛选出来。
修改后的Foo类实现如下:
class Foo def initialize(values) @values = values end def =~(pattern) # 只要有一个内部值匹配pattern,就返回非nil(0是Ruby匹配成功的惯例返回值) @values.any? { |v| v =~ pattern } ? 0 : nil end end
测试验证:
[Foo.new(["foo", "bar"]), Foo.new(["zoo"])].grep(/oo/) # => [#<Foo:0x00007f... @values=["foo", "bar"]>, #<Foo:0x00007f... @values=["zoo"]>]
这个实现同样适配grep_v方法,会自动排除内部值不匹配正则的Foo实例。
内容的提问来源于stack exchange,提问作者23tux
相关产品推荐
相关产品推荐

