2014-01-07 91 views
7

我不明白爲什麼在Ruby中,Array#sliceArray#slice!的行爲與Array#sortArray#sort!的行爲不同(以一種方式返回一個新數組的結果而另一個對當前對象起作用)。爲什麼Array#slice和Array#slice!行爲有所不同?

隨着sort第一個(沒有爆炸),返回當前數組的排序副本,並sort!排序當前數組。

slice,返回與指定的範圍內的陣列,和slice!刪除從當前對象在指定的範圍。

Array#slice!的行爲如何,而不是使當前對象成爲具有指定範圍的Array?

實施例:

a = [0,1,2,3,4,5,6,7,8,9] 

b = a.slice(2,2) 

puts "slice:" 
puts " a = " + a.inspect 
puts " b = " + b.inspect 

b = a.slice!(2,2) 
puts "slice!:" 
puts " a = " + a.inspect 
puts " b = " + b.inspect 

輸出:

slice: 
    a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
    b = [2, 3] 
slice!: 
    a = [0, 1, 4, 5, 6, 7, 8, 9] 
    b = [2, 3] 

http://ideone.com/77xFva

+2

使用'!'在一個方法上沒有設置行爲,它只是在那裏表明該方法以某種方式改變了輸入,同時也具有完全相同的輸出。您可以將其添加到您編寫的任何方法的末尾。 – tpbowden

回答

3

#slice#slice!行爲是等效的:既「返回一個子陣列開始於開始索引並持續長度元件」,以相同的方式作爲#sort#sort!返回一個排序後的數組或#reverse#reverse!返回一個反轉陣列。

區別在於bang方法也會修改對象本身。

a = [4,2,6,9,1,5,8] 
b = a.dup 
a.sort == b.sort!    # => true 
a == b      # => false 

b = a.dup 
a.reverse == b.reverse!  # => true 
a == b      # => false 

b = a.dup 
a.slice(2,2) == b.slice!(2,2) # => true 
a == b      # => false 
+0

這不是用戶所要求的。他知道這一點,他在問一個設計決定。具體來說,爲什麼切片不會用結果替換當前對象。 –

+2

'#slice'(和'#slice!')_「如果索引超出範圍則返回nil」_。這種情況與用返回值 – wacko

+0

替換對象的想法不一致,這可能是迄今爲止我讀過的最好的解釋之一。 +1 –

1

!或爆炸的方法在紅寶石通常變異現有的對象,而不是所述非爆炸方法等效,它返回一個新目的。如果要修改現有對象,請使用bang方法選項。

編輯: 爲了解決設計決策,我不是馬茨,但我會猜測,因爲slice的性質是返回一個子集,它返回在每種情況下的子集。對於其他爆炸方法,如gsubsort,您正在修改(可能)整個字符串/對象,以便它可以返回一個副本,或者返回包含更改的原件。

+1

這不是用戶所要求的。他知道這一點,他在問一個設計決定。具體來說,爲什麼切片不會用結果替換當前對象。 –

+0

@SimoneCarletti可能有幫助嗎? –

0

我覺得背後的設計決策的想法是,如果你調用Array#slice!那麼你已經有了一個指向數組的切片(假設你把它分配給一個變量)。邏輯決策是修改對象,以便切片不再位於原始數組中。

例如,您可以看到這在循環中是如何有用的。如果你想繼續分析陣列的前3個元素,用這3個元素做一些事情,當沒有更多元素時停止,你可以使用Array#slice!,它最終會破壞數組。

現在,如果您想象示例中的數組是一個隊列或堆棧,那麼爲什麼要刪除數組的某些部分是有意義的。

相關問題