在Ruby中将连续过滤器应用于数组

时间:2015-05-16 02:02:10

标签: ruby functional-programming

我有一些对象的数组,可能是字符串或数字。我想对这个数组应用一些任意的过滤器,我希望能够指定过滤器的顺序。这是一个例子(我知道在这个玩具示例中,顺序并不重要,但我希望能够为另一个案例指定):

Embedded

现在,我知道我可以这样做:

filters = [:filter_odd, :filter_multiple_five]
all = (1..10).to_a #[1, 2, ... 10]

filter(all, filters)
# should return [5]

# where, i.e.:
private

def filter_odd(numbers)
  numbers.select(&:odd?)
end

def filter_multiple_five(numbers)
  numbers.select { |number| number%5 == 0 }
end

但随着我的要求发生变化,我不得不添加更多过滤器,这样做并不是很令人满意。我在Ruby中寻找一种干净,实用的方法。

2 个答案:

答案 0 :(得分:2)

好的,扰流板,我找到了一个解决方案。由于我无法在任何地方找到这个确切的问题,我决定在这里发布:

odds = filter_odd(all)
filter_multiple_five(odds)

所以,如果你有一些过滤方法:

def filter(array_of_numbers, filters)
  filters.inject(array_of_numbers) do |remaining_numbers, filter|
    send(filter, remaining_numbers)
  end
end

过滤方法名称列表(作为符号)和一些数据:

private

def filter_odd(numbers)
  numbers.select(&:odd?)
end

def filter_multiple_five(numbers)
  numbers.select { |number| number%5 == 0 }
end

调用filters = [:filter_odd, :filter_multiple_five] all = (1..10).to_a #[1, 2, ... 10] 会返回正确的结果。在第一个过滤器之后,它只产生块的几率,在第二个过滤器之后它返回奇数倍的5:

filters

答案 1 :(得分:2)

您可以使用blocks,这是一种灵活的方式。如果您不熟悉块,可以将其用作参考:understanding-ruby-blocks-procs-and-lambdas

class Array
   def filter
       self.select{ |e| yield(e)} if block_given?
   end
end

arr = (1..10).to_a
puts arr.filter{ |n|  n % 5 == 0 }.inspect
puts arr.filter{ |n|  n.odd? }.inspect
puts arr.filter{ |n|  n % 3 == 0 }.inspect

输出:

[5, 10]
[1, 3, 5, 7, 9]
[3, 6, 9]