8

我不明白为什么在 Ruby 中, Array#slice其行为与andArray#slice!不同(其中一个在新数组上返回结果,而另一个在当前对象上工作)。Array#sortArray#sort!

使用sort第一个(没有 bang),返回当前 Array 的排序副本,并对当前 Array 进行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

4

3 回答 3

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
于 2014-01-07T17:55:46.500 回答
1

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

编辑:为了解决设计决策,我不是 Matz,但我猜想因为它的本质slice是返回一个子集,所以它在每种情况下都会返回子集。对于其他 bang 方法,例如gsub,或者sort您正在修改(可能)整个字符串/对象,因此它要么返回副本,要么返回带有更改的原始文件。

于 2014-01-07T16:59:04.977 回答
0

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

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

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

于 2014-01-07T22:25:02.183 回答