假设我想使用自定义方法选择数组中的元素。为了论证我会使用奇偶校验。
现在一般来说,使用
之间是否有任何良好的做法/建议可供选择class Integer # Adding method to the Integer class
def my_fancy_select
self % 2 == 0
end
end
puts my_array.select(&:my_fancy_select)
和
def my_fancy_select(i) # could be a private method
i % 2 == 0
end
puts my_array.select{|i| my_select(i)}
,
puts my_array.select{|i|
i % 2 == 0 # Directly passing a block
}
,甚至使用Procs?
答案 0 :(得分:2)
除非您认为该方法真正解决了所有整数的行为,否则应避免添加Integer
。即便如此,你也要注意碰撞。
除此之外,没有任何内在的理由选择第二种或第三种形式而不是另一种形式,特别是在你的简单例子中。
代码块和方法提供了不同的代码重用方法。当重复“外部”模式时,块可以很好地工作,并且您只想在内部改变几行。当您需要在多个位置执行完全相同的“内部”逻辑时,方法可以很好地工作。
如果您的过滤逻辑确实在多个地方重复,那么我倾向于将它作为mixin的方法,或者合适的自定义类的类方法,并在块中调用该方法。这是你的第二个例子。否则,带有块的直接单行是适合的目的,我可以在适当的位置阅读它,这提供了一点点可读性优势(假设代码保持DRY) - 这是你的第三个例子。
答案 1 :(得分:2)
一种非常优雅的方法是创建一个具有适当名称的proc或lambda:
even_numbers = -> x {x.even?}
numbers_that_start_with_three = -> x {x.to_s[0] == '3'}
p [11,22,33,4,5,6].select(&even_numbers) #=> [22, 4, 6]
p [11,22,33,4,5,6].select(&numbers_that_start_with_three) #=> [33]
答案 2 :(得分:1)
我看待这样的问题的方式是“是什么让代码最容易阅读和理解?”,因为所有的解决方案都能有效地做同样的事情。
在我看来,我更喜欢这个:
def my_select(i) # could be a private method
i % 2 == 0
end
puts my_array.select{|i| my_select(i)}
主要是因为它最容易阅读和理解。我也不喜欢“猴子修补”核心类(如Integer
),除非没有其他解决方案。