2012-12-09 68 views
1

返回我有一個類Test返回從一個塊的值,而不脫離方法

class Test 
    attr_accessor :data 
    def initialize 
    @data = [0, 1, 2, 3] 
    end 
    def map 
    @data.map!{|i| i = yield i } 
    end 
end 

和我嘗試使用它喜歡:

a = Test.new 

a.map{|i| 
    if(i==2) 
    i+=1 
    break i #<--- -This line is the focus 
    else 
    1 
    end 
} 

puts a.data 

我期望的輸出是[1, 1, 3, 3]。相反,我得到[1, 1, 2, 3]map中塊的最後一次迭代不會返回修改後的i

我將break i替換爲next i。這按我的預期執行,並生成輸出[1, 1, 3, 1]

我該如何修改這段代碼(或者,理想情況下,我在第二個代碼片段中指出的那一行),以便得到輸出[1, 1, 3, 3]?換句話說,我該如何完成塊完成,但將最後一個值傳回map?有沒有一個簡潔可讀的方法來做到這一點(另外,例如,切換布爾標誌break_now)?

回答

-1

你必須這樣做:

a.map{ |i| (i % 2 == 0) ? i + 1 : i } 

當您使用地圖功能,如果你想改變你不改變「一個」變量「一個」變量做到這一點:

a.map!{ |i| (i % 2 == 0) ? i + 1 : i } 

「我」的新值是由塊的價值迴歸,所以不要做這樣的事情:因爲如果你這樣做

a.map{|i| i = 1 } 

a.map{|i| i = 1; 5 } 

的結果將是:

[5, 5, 5, 5] 
+2

我認爲他詢問如何同時利用當前值的,而不是在本例中提到的具體數值離開塊。 –

1

我假設你問如何離開塊,並充分利用了計算,而不是如何計算一組特定的最後一個值的數字;對於後者來說,可能有一個聰明的單線程。

怎麼是這樣的:

class Test 
    attr_accessor :data 

    def initialize 
    @data = [0, 1, 2, 3] 
    end 

    def modify 
    @data.map! {|i| yield i } 
    end 
end 

a = Test.new 
a.modify do |i| 
    break i if @done 
    @done = i == 2 
    @done ? (i + 1) : 1 
end 

puts a.data 

另外一個思想— #map是在Ruby中具有特定接口的重要方法。在你的例子中,你通過修改Test中的字段來違反界面。由於這個原因,我用名稱#modify代替。

+0

非常感謝您的回答。你能否澄清一下#map的意圖是什麼 - 我認爲這很重要? – Paul

+0

@保羅:這取決於它是如何被調用,'#map'返回'Array'或'Enumerable'無需修改就調用它的對象。 –

+0

@Paul:我應該糾正以前的評論 - 做一個枚舉器,不一定是'Enumerable'。 –

0

通常,您可以通過修改已生成的值來避免這種情況。例如,如果你的陣列組成的字符串,而不是Fixnums的:

class Test 
    attr_accessor :data 

    def initialize 
    @data = %w{a b c d} 
    end 

    def map 
    @data.map! { |i| yield i } 
    end 
end 

a = Test.new 
a.map do |i| 
    if i == 'c' 
    i.next! 
    break 
    else 
    'b' 
    end 
end 

p a.data #=> ["b", "b", "d", "d"] 

你的榜樣的問題是this

Fixnum對象對象有直接的價值。這意味着當它們被分配或作爲參數傳遞時,實際的對象被傳遞,而不是對該對象的引用。賦值不會成爲Fixnum對象的別名。有效的只有一個對於任何給定的整數值Fixnum對象的對象實例...

Fixnums不能就地進行更改,所以你的下部區塊表達i += 1不上塊影響i值。這就是爲什麼你在你的例子中得到2,但在我的例子中爲d