【问题标题】:Why Array#slice and Array#slice! behave differently?为什么是 Array#slice 和 Array#slice!表现不同?
【发布时间】:2014-01-25 11:21:07
【问题描述】:

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

sort 第一个(不带 bang)返回当前 Array 的排序副本,sort! 对当前 Array 进行排序。

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

【问题讨论】:

  • 在方法上使用! 没有固定的行为,它只是表明该方法以某种方式改变了输入,同时也具有完全相同的输出。您可以将其添加到您编写的任何方法的末尾。

标签: ruby behavior design-decisions


【解决方案1】:

#slice#slice! 行为是等效的:都“返回从 start 索引开始并继续 length 元素的子数组”,与 @ 相同987654323@ 和 #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

【讨论】:

  • 这不是用户要求的。他知道这一点,他在询问设计决策。具体来说,为什么要切片!不会用结果替换当前对象。
  • #slice(和#slice!“如果索引超出范围,则返回 nil”。这种情况与用返回值替换对象的想法是不相容的
  • 这可能是迄今为止我读过的最好的解释之一。 +1
  • 我不得不接受这个 =/ 我对 bang-methods 有错误的想法。
【解决方案2】:

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

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

【讨论】:

  • 这不是用户要求的。他知道这一点,他在询问设计决策。具体来说,为什么要切片!不会用结果替换当前对象。
  • @SimoneCarletti 也许有帮助?
【解决方案3】:

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

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

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

【讨论】:

    猜你喜欢
    • 2018-12-05
    • 2023-02-09
    • 1970-01-01
    • 2023-04-07
    • 2015-08-12
    • 1970-01-01
    • 2022-11-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多