简体   繁体   English

在 Ruby 中,从技术上讲,没有块的 array.reject 或 array.select 会做什么?

[英]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.rejectarray.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 ,但我很好奇为什么rejectselect没有块什么都不做 - 我期待一个{ |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#cycleEnumerator#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_charEnumerator#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.您可能想将enum1enum2视为“复合”枚举数。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM