1

私の小さなプロジェクトで、基準によるフィルターのアプローチを実装しようとしています。名前、年、ジャンルのフィルターがある 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 クラスの演算子ですが、フィルター オブジェクトを組み合わせて、フィルターに渡すことができる 1 つのオブジェクトになるようにする方法がわかりません。どんなアイデアでも喜んで受け入れます。:)

これまでの私の最善のアイデアは、すべての Filter.new に対して proc を作成し、それらを &,| で結合することです。と !方法ですが、方法がわかりません。私はこのようなものがうまくいくと思っていますが、そうではありません:D

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

そして、すべての @movies アイテムでこれを呼び出します。procs の組み合わせについて教えてください。または、より良い解決策を提案してください。ありがとうございました。

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 に答える