2014-01-07 92 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!,它最终会破坏数组。

现在,如果您想象示例中的数组是一个队列或堆栈,那么为什么要删除数组的某些部分是有意义的。

相关问题