为什么Array#slice和Array#slice!表现不同?

时间:2014-01-07 16:52:58

标签: ruby behavior design-decisions

我无法理解为什么在Ruby中,Array#sliceArray#slice!的行为与Array#sortArray#sort!的行为不同(就像在新数组中返回结果一样)而另一个在当前对象上工作。)

使用sort第一个(没有爆炸),返回当前数组的已排序副本,sort!对当前数组进行排序。

slice,返回具有指定范围的数组,slice! 删除当前对象的指定范围。

Array#slice!的行为是什么原因,而不是让当前对象成为具有指定范围的数组?

示例:

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

3 个答案:

答案 0 :(得分:3)

#slice#slice!行为是等效的:“返回从开始索引开始的子数组并继续 length 元素”,与#sort#sort!相同的方式返回已排序的数组或#reverse#reverse!返回反向数组。

不同之处在于爆炸方法也会修改对象本身。

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

答案 1 :(得分:1)

ruby中的

!或bang方法通常会改变现有对象而不是返回新对象的非等价方法等效方法。如果要修改现有对象,请使用bang方法选项。

编辑: 为了解决设计决策,我不是Matz,但我猜这是因为slice的本质是返回一个子集,它会在每种情况下返回子集。对于其他爆炸方法,例如gsubsort,您正在修改(可能)整个字符串/对象,以便它返回副本或返回原始变量。

答案 2 :(得分:0)

我认为设计决策背后的想法是,如果你调用Array#slice!,那么你已经有一个指向数组切片的指针(假设你将它分配给一个变量)。逻辑决定是修改对象,使切片不再在原始数组中。

例如,您可以看到这在循环中如何有用。如果你想继续分析数组的前3个元素,用这3个元素做一些事情,并在没有更多元素时停止,你可以使用Array#slice!并最终破坏数组。

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