1

我正在尝试在我的一个小项目中实施按标准过滤的方法。我有一个过滤器类,其中有名称、年份、流派的过滤器。例如:

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.new 创建一个 proc,然后将它们组合在 &,| 和 !方法,但我不知道如何。我在想这样的事情可以工作,但是,它没有:D

proc { |movie| proc { |movie| movie.name == "The Godfather" } && proc { |movie| movie.year== "1972" }

然后用每个 @movies 项目调用它。你能帮我解决合并过程的问题吗,或者提出一个更好的解决方案。谢谢你。

4

1 回答 1

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">]
于 2012-10-30T11:25:01.143 回答