[英]In Ruby, what - technically - does array.reject or array.select without a block do?
So far as I can tell, array.reject
and array.select
do nothing:到目前为止,我所知道的,
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]
For the code I was trying to write, compact
was what I needed, but I'm very curious why reject
and select
without a block do nothing - I was expecting a default block of { |e| e }
对于我试图编写的代码,我需要的是
compact
,但我很好奇为什么reject
和select
没有块什么都不做 - 我期待一个{ |e| e }
的默认块{ |e| e }
so reject
would be compact
and 'select' would be some weird anti-compact. { |e| e }
所以reject
将是compact
而“选择”将是一些奇怪的反紧凑。
What is the default block doing?默认块在做什么?
Edit: Sorry, I missed off the '.to_a' on the ends of the expressions above, which I was hoping would trigger some sort of lazy evaluation and make the reject/select enumeration do something useful.编辑:抱歉,我错过了上面表达式末尾的 '.to_a',我希望它会触发某种惰性评估并使拒绝/选择枚举做一些有用的事情。 I normally cut&paste my examples to avoid this sort of thing.
我通常会剪切和粘贴我的示例以避免此类事情。
makes an Enumerator
of it:制作它的
Enumerator
:
en = [1,2,3].reject
# => #<Enumerator: [1, 2, 3]:reject>
en.each{|n| n == 1}
# => [2, 3]
A block is optional for many Ruby methods.对于许多 Ruby 方法来说,块是可选的。 When no block is given an enumerator is usually returned.
当没有给出块时,通常会返回一个枚举器。 There are at least a couple of reasons you might want an enumerator.
您可能需要枚举器的原因至少有几个。
#1 Use the enumerator with the methods in the class Enumerator . #1 将枚举器与类Enumerator 中的方法一起使用。
Here's an example.这是一个例子。 Suppose you wish to alternate the case of letters in a string.
假设您希望改变字符串中字母的大小写。 One conventional way is:
一种传统方式是:
"oh happy day".each_char.with_index.map { |c,i| i.odd? ? c.upcase : c.downcase }.join
#=> "oH HaPpY DaY"
but you could instead write:但你可以写:
enum = [:odd, :even].cycle
"oh happy day".each_char.map { |c| enum.next==:odd ? c.upcase : c.downcase }.join
or perhaps也许
enum = [:upcase, :downcase].cycle
"oh happy day".each_char.map { |c| c.send(enum.next) }.join
See the docs for Array#cycle and Enumerator#next .请参阅Array#cycle和Enumerator#next的文档。
#2 Use enumerators to chain methods #2 使用枚举器链接方法
In my first example above, I wrote:在上面的第一个示例中,我写道:
"oh happy day".each_char.with_index.map...
If you examine the docs for String#each_char and Enumerator#with_index you will see that both methods can be used with or without a block.如果您检查String#each_char和Enumerator#with_index的文档,您会发现这两种方法都可以在有或没有块的情况下使用。 Here they are both used without a block.
在这里,它们都在没有块的情况下使用。 That enables the three methods to be chained .
这使得可以链接三个方法。
Study the return values in the following.研究下面的返回值。
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>
You might want to think of enum1
and enum2
as "compound" enumerators.您可能想将
enum1
和enum2
视为“复合”枚举数。
You show the return value of:您显示的返回值是:
[nil, false, true].reject
to be:成为:
#=> [nil, false, true]
but that is not correct.但这是不正确的。 The return value is:
返回值为:
#<Enumerator: [nil, false, true]:reject>
If we write:如果我们写:
enum = [nil, false, true].reject
then:然后:
enum.each { |e| e }
#=> [nil, false]
(which, since Ruby v2.3, we could write enum.reject(&:itself)
). (从 Ruby v2.3 开始,我们可以编写
enum.reject(&:itself)
)。 This uses the method Enumerator#each , causing enum
to invoke Array#each because reject
's receiver is an instance of the class Array
.这使用方法Enumerator#each ,导致
enum
调用Array#each因为reject
的接收者是类Array
的实例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.