我正在尝试在我的一个小项目中实施按标准过滤的方法。我有一个Filter类,其中我有名称,年份,流派的过滤器。例如:
Filter.new.name("The Shawshank Redemption")
Filter.new.year("1994")
Filter.new.genre("drama")
我还有一个电影列表,每个电影都是一个具有方法名称,年份和流派的对象。我希望能够做到以下几点(MoviesContainer只是一个有@movies列表的类):
MoviesContainer.filter Filter.new.name("The Godfather") & Filter.new.year("1972") | Filter.year("1974")
我很容易超载|,&而且!我的Filter类中的运算符,但我不知道如何组合过滤器对象,以便它们成为我可以传递给过滤器的一个对象。 我很乐意接受任何想法。 :)
到目前为止,我最好的想法是为每个Filter.new创建一个proc,然后将它们组合在&,|中而且!方法,但我不知道如何。我认为这样的事情可行,但事实并非如此:D
proc { |movie| proc { |movie| movie.name == "The Godfather" } && proc { |movie| movie.year== "1972" }
然后用每个@movies项调用它。 你能帮我解决一下这个组合过程的事情,或者提出一个更好的解决方案。谢谢。
答案 0 :(得分:0)
也许是这样的?
class Filter
attr_accessor :proc
class <<self; alias :old_new :new end
def self.new attribute, value
old_new.tap{|f| f.proc = ->x{x.send(attribute) == value}}
end
def & other
self.class.old_new.tap{|f| f.proc = ->x{proc.call(x) && other.proc.call(x)}}
end
def | other
self.class.old_new.tap{|f| f.proc = ->x{proc.call(x) || other.proc.call(x)}}
end
def !
self.class.old_new.tap{|f| f.proc = ->x{!proc.call(x)}}
end
end
class Movie
attr_accessor :name, :year, :genre
end
MoviesContainer = [
Movie.new.tap{|m| m.name = "The Godfather"; m.year = "1972"},
Movie.new
]
module Enumerable
def filter f
select(&f.proc)
end
end
filter1 = Filter.new(:name, "The Godfather")
filter2 = Filter.new(:year, "1972")
filter3 = Filter.new(:year, "1974")
MoviesContainer.filter(filter1 & filter2 | filter3)
# => [#<Movie:0x000000017dba08 @name="The Godfather", @year="1972">]