如何在ruby中筛选多个条件的列表?

1 ruby filter conditional-statements

我想在我有三个方法,一个过滤器类:name,genre,和year.我要筛选的电影列表,其中每个对象都有一个name,title并且year,多个标准.

我无法弄清楚如何做到这一点.例如:

Filter.name("Batman") & Filter.genre("Drama") | !Filter.year(2001)
Run Code Online (Sandbox Code Playgroud)

我试图将过滤器字段保留在列表中[name => batman, genre=>drama],依此类推,但运算符(特别是or(|))正在困扰我.

我接受任何想法.

Ana*_*ani 8

试试这个:

让ary包含对象列表

ary.select{|obj| obj.name == 'batman' && obj.genre == 'drama' || obj.year != 2001}
Run Code Online (Sandbox Code Playgroud)

我假设你有一个列表中的对象,注意&&和|| 运营商的精神

或者你期待这个?

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)
Run Code Online (Sandbox Code Playgroud)


the*_*Man 5

您想要的功能自然适合Enumerable的select,Array继承.

因为你在谈论列表,AKA,数组,所以使用select来确定你的电影是否符合你的标准是很自然的,而不是将它们传递给方法.

单独的Filter类也不适合Ruby-way.考虑为电影列表对数组进行子类化,并添加一个以条件为参数的过滤方法.

以下是我编写该功能的方法,但是我认为这样做的方式更像Ruby:

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)
Run Code Online (Sandbox Code Playgroud)

我在Movie类中使用了哈希,因为它更快.这也是一个更脏的方式,但它的工作原理.

这是运行代码的输出:

[#<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}>]
Run Code Online (Sandbox Code Playgroud)

过滤电影的实际流程符合我们通常编写Ruby代码的方式.它可以做得更好,但这是一个开始.