2016-03-31 81 views
-3

到目前爲止,我所知道的,array.rejectarray.select無可奈何:在Ruby中,什麼 - 技術上 - 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是我需要什麼,但我很好奇,爲什麼rejectselect沒有塊什麼也不做 - 我期待{ |e| e }的默認塊,所以rejectcompact和'選擇'將是一些奇怪的反緊湊。

默認塊在做什麼?


編輯:抱歉,我沒掉上面的表達式的末端,我希望會引發某種懶惰的評價,並拒絕/選擇枚舉做有用的東西「.to_a」。我通常會刪除&粘貼我的示例以避免這種情況。

+6

它返回[Enumerator](http://ruby-doc.org/core-2.1.5/Enumerator.html) – fl00r

+1

在我的irb中,''[nil,false,true] .reject =>#',這幾乎可以回答這個問題。 –

+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#cycleEnumerator#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> 

你可能要考慮的enum1enum2爲「化合物」統計員。

您展示的返回值:

[nil, false, true].reject 

是:

#=> [nil, false, true] 

但是這是不正確的。返回值是:

#<Enumerator: [nil, false, true]:reject> 

如果我們寫:

enum = [nil, false, true].reject 

則:

enum.each { |e| e } 
    #=> [nil, false] 

(其中,因爲紅寶石V2.3,我們可以寫enum.reject(&:itself))。這使用方法Enumerator#each,導致enum調用Array#each,因爲reject的接收方是類Array的實例。

+0

感謝您提供這樣一個完整的答案,尤其是關於拒絕枚舉的細微之處是由與創建點不同的塊進行操作。我經常使用鏈式成語,但沒有考慮過什麼類型的「點之間」操作。 (我發現自己在編寫'.each {| e | e}'時很吝嗇,但我討厭猴子補丁,所以我只需要渴望像'.it'方法那樣定義爲在未來的某個版本中Ruby。:) –

+0

@ android.weasel \t你爲什麼要寫'.each {| e | e}'? –

2

使得它的一個Enumerator

en = [1,2,3].reject 
# => #<Enumerator: [1, 2, 3]:reject> 
en.each{|n| n == 1} 
# => [2, 3] 
+0

您是對的。我通常複製粘貼我的例子,但沒有那個時間。令我感到困惑的是,試圖通過使用.to_a來強制執行某些有用的枚舉操作,只是將所有值都返回,而不會在任何地方發生拒絕。 @CarySwoveland的迴應顯示,它需要用'each {| e | e}'迭代,以使它做一些有用的事情 - 這就是我最終做的事情,但不明白爲什麼(仍然)看起來像是明顯的默認行爲,取得。 –

相關問題