How to filter list on multiple criteria in ruby?
我想创建一个filter类,其中有三个方法:
我不知道该怎么做。例如:
1 | Filter.name("Batman") & Filter.genre("Drama") | !Filter.year(2001) |
我试图将筛选字段保存在一个列表
我接受任何想法。
试试这个:
让ARY包含对象列表
1 | ary.select{|obj| obj.name == 'batman' && obj.genre == 'drama' || obj.year != 2001} |
我假设您在列表中有对象,请注意&;&;和运算符优先级
或者你期待着呢?
1 2 3 4 5 6 7 8 | class Filter def self.search_by(ary, name, genre, year) ary.select{|obj| obj.name == name && obj.genre == genre || obj.year != year} end end ary = all_films # assume function returns all films Filter.search_by(ary, 'batman', 'drama', 2001) |
您想要的功能很自然地适合Enumerable的Select,它继承了哪个数组。
因为你说的是一个列表,也就是数组,用select来确定你的电影是否符合你的标准是很自然的,它是建立在这个基础上的,而不是传递给一个方法。
单独的过滤器类也不适合Ruby。考虑为电影列表子分类数组,并添加一个将条件作为参数的筛选方法。
下面是我编写这个功能的方法,但我认为这样做更像Ruby:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | require 'pp' class Movies < Array def initialize(*movies) super(movies) end def filter(criteria={}) self.select{ |m| criteria.all?{ |c, v| m.send(c, v) } } end end class Movie def initialize(attributes={}) @movie = attributes end def name(t) case t when Regexp @movie[:name][t] when String @movie[:name] == t end end def genre(g) @movie[:genre] == g end def year(y) @movie[:year] == y end end movies = Movies.new( Movie.new(name: 'Batman', genre: 'Drama', year: 2001), Movie.new(name: 'The Shawshank Redemption', genre: 'Drama', year: 1994), Movie.new(name: 'Raiders of the Lost Ark', genre: 'Action', year: 1981) ) pp movies.filter(year: 1981) pp movies.filter(genre: 'Drama', year: 2001) pp movies.filter(name: /redemption/i) |
我在电影课上用了一个哈希表,因为它更快。这也是一个更脏的方式,但它起作用。
下面是运行代码的输出:
1 2 3 4 5 6 | [#<Movie:0x007ff7b191ffb8 @movie={:name=>"Raiders of the Lost Ark", :genre=>"Action", :year=>1981}>] [#<Movie:0x007ff7b1920260 @movie={:name=>"Batman", :genre=>"Drama", :year=>2001}>] [#<Movie:0x007ff7b19200d0 @movie={:name=>"The Shawshank Redemption", :genre=>"Drama", :year=>1994}>] |
过滤电影的实际流程符合我们通常编写Ruby代码的方式。它可以做得更好,但这是一个开始。
所以你要拿后者,
这样地:
1 | Filter.name("Batman") && Filter.genre("Drama") || !Filter.year(2001) |
有关详细信息,请参阅http://www.tutorialspoint.com/ruby/ruby_operators.htm。