据我所知,array.reject
和array.select
什么都不做:
[nil, false, true].reject # Should have been reject.to_a for this example.
=> [nil, false, true]
[nil, false, true].select # Should have been select.to_a for this example.
=> [nil, false, true]
对于我尝试编写的代码,compact
是我所需要的,但我很好奇为什么reject
和select
没有阻止什么都没做 - 我期待着{ |e| e }
的默认阻止,reject
为compact
,“选择”将是一些奇怪的反紧凑。
默认阻止做什么?
编辑:对不起,我错过了上面表达式末尾的'.to_a',我希望这会触发某种懒惰的评估,并使拒绝/选择枚举做一些有用的事情。我通常剪切和粘贴我的例子来避免这种情况。
答案 0 :(得分:2)
生成Enumerator
:
en = [1,2,3].reject
# => #<Enumerator: [1, 2, 3]:reject>
en.each{|n| n == 1}
# => [2, 3]
答案 1 :(得分:2)
对于许多Ruby方法,块是可选的。当没有给出块时,通常返回枚举器。至少有几个原因你可能想要一个普查员。
#1将枚举数与类Enumerator中的方法一起使用。
这是一个例子。假设您希望在字符串中替换字母大小写。一种传统方式是:
"oh happy day".each_char.with_index.map { |c,i| i.odd? ? c.upcase : c.downcase }.join
#=> "oH HaPpY DaY"
但你可以写一下:
enum = [:odd, :even].cycle
"oh happy day".each_char.map { |c| enum.next==:odd ? c.upcase : c.downcase }.join
或者
enum = [:upcase, :downcase].cycle
"oh happy day".each_char.map { |c| c.send(enum.next) }.join
请参阅Array#cycle和Enumerator#next的文档。
#2使用枚举器链接方法
在我上面的第一个例子中,我写道:
"oh happy day".each_char.with_index.map...
如果您检查String#each_char和Enumerator#with_index的文档,您会发现这两种方法都可以在有或没有块的情况下使用。在这里他们都使用没有块。这使得三种方法可以链接。
研究以下的返回值。
enum0 = "oh happy day".each_char
#=> #<Enumerator: "oh happy day":each_char>
enum1 = enum0.with_index
#=> #<Enumerator: #<Enumerator: "oh happy day":each_char>:with_index>
enum2 = enum1.map
#=> #<Enumerator: #<Enumerator: #<Enumerator:
# "oh happy day":each_char>:with_index>:map>
您可能希望将enum1
和enum2
视为“复合”枚举数。
您显示的返回值为:
[nil, false, true].reject
是:
#=> [nil, false, true]
但这不正确。返回值为:
#<Enumerator: [nil, false, true]:reject>
如果我们写:
enum = [nil, false, true].reject
然后:
enum.each { |e| e }
#=> [nil, false]
(从Ruby v2.3开始,我们可以编写enum.reject(&:itself)
)。这使用方法Enumerator#each,导致enum
调用Array#each,因为reject
的接收者是类Array
的实例。