【问题标题】:How does negative index work with `Array#[]=`?负索引如何与 `Array#[]=` 一起使用?
【发布时间】:2013-02-24 07:48:57
【问题描述】:

我试着看看Array#[]= 是如何工作的,然后玩了一下:

enum[int] = obj → obj
enum[start, length] = obj → obj
enum[range] = obj → obj

问题 1

我有一个数组b 在其0 索引处保存nil

b = []
b[0]   # => nil

我尝试在下面的代码中将nil 替换为整数10

b[-1] = 10 # => IndexError: index -1 too small for array; minimum: 0

为什么上面的代码不起作用,而下面的代码起作用?对于大小为1 的数组,为什么索引0-1 的处理方式不同?

b[0] = 5   # => 5
b[-1] = 10 # => 10

问题 2

我创建了一个大小为2 的数组,并执行了以下操作:

a = [1,2]

a[-3] = 3       # => IndexError: index -3 too small for array; minimum: -2
a[-3] = [3]     # => IndexError: index -3 too small for array; minimum: -2
a[-3..-4] = [3] # => RangeError: -3..-4 out of range

我相信负索引永远不会增加数组的大小,但我不知道为什么。为什么下面的代码成功了?

a[-2..-3] = [3,4] #=> [3, 4]

【问题讨论】:

  • 好问题,正在寻找原因
  • @Arindam 感谢您的补充.. :)
  • b = [] 这样的空数组 持有nil。如果给定索引处的值不存在,它只会返回nil> b[6789] => nil
  • @DavidUnric Humm 你完全正确。

标签: ruby arrays


【解决方案1】:

我建议你看看Array documentation 的第一段。它出人意料地说:“负索引被假定为相对于数组的末尾——也就是说,索引 -1 表示数组的最后一个元素,-2 是数组中的倒数第二个元素,因此开。”

这意味着,当且仅|N| <= a.size 时,您可以设置a[-N]th 元素。这就是 a = [1,2] ; a[-3] = 3 失败 (3 > 2) 的原因。

另一方面,红宝石数组[可能]没有记录的功能:a[INBOUNDS_IDX..NONSENSE_IDX]=SMTH插入SMTH之前INBOUNDS_IDX索引:

a=[1,2]
a[2..0]='a'
a[2..1]='b'
a[2..-100]='c'
# ⇒ [1, 2, "c", "b", "a"]
a[2..-1]='q'
# ⇒ [1, 2, "q"]

这里的废话意思是“小于 INBOUNDS_IDX,并且不能作为负数表示的索引处理”(这就是为什么上面示例中的 a[2..-1] 被视为 a[2..(a.size - 1)]。)

【讨论】:

  • 我认为我没有找到a[-2..-3] = [3,4] #=> [3, 4] 的答案。你能指点我这里吗?
  • @LoveConcept a[-2..-3] = [3,4] #=> [3, 4] 表示[3,4] 是从Array#[] 方法返回的值。如果您使用puts a 打印a 值,您将看到#⇒[3,4,1,2] 符合预期。
  • 如果你尝试a = [1,2] 然后a[-3] = 5 会产生错误IndexError: index -3 too small for array; minimum: -2。但后来尝试a[-2..-4] =15 工作。在这里我很困惑。你能帮我理解这个概念吗?新数组看起来像>> a #=> [15, 1, 2]。这里数组也借助负索引设置或添加新元素,但为什么不第一次尝试呢?
  • 我认为我无法比我在评论中所做的更好地解释它(从“另一方面......”开始,直到评论结束。)
  • 嗯,你做到了。真的这件事没有记录在案。但感谢表达事实。 +1给你。
【解决方案2】:

观察 #1

-1 索引与最后一个元素相关,如果数组没有大小 [],则在使用一个或多个元素初始化它之前不能使用它。

观察 #2:

是的,你是对的,负索引永远不会增加数组的大小,如果只引用数组中一个具体的现有位置。不要认为数组是循环的(0 索引指向 N-1 索引),所以你不能使用任何负索引认为它是有效的

【讨论】:

  • 如果是这样,你会如何解释a[-2..-3] = [3,4]
【解决方案3】:

第一季度:

一个空数组有 0 个元素,所以当你尝试将它的元素设置为 0,负索引 -1 时,它会报错。 因为负索引从末尾循环遍历数组。

所以 a = []; a[-1] = 3 不可能

a) 获取最后位置的元素,因为它是 null

b) 设置它的值。因为它从未被捕获。

a[0] = 5 会起作用,因为你告诉编译器这样做

a) 抓取第一个元素,

b) 如果不存在,则创建一个,然后将其分配给您请求的值。

参见official api doc,特别提到正索引可以增加大小,超过数组开头的负索引会引发错误。

第二季度:

上面的解释几乎也回答了第二个问题。

给定a = [1,2]

a[-3] = 3 导致第一个中断点。您正在尝试从末尾访问第三个元素,该元素不存在。按照设计,它会崩溃。

a[-2..-3] 在定义数组的捕获范围内。

您要求解释器从最后一个元素(在本例中为从前面的第一个)捕获第二个元素,并尝试调用一个要求它增加数组大小的范围,并用您请求的任何内容填充它。

令人高兴的是,一切都还好,如您所愿。很高兴知道。

【讨论】:

  • “并尝试调用一个范围”——这不太正确。 a[-2..-3]完全视为a[-2..0],一般来说,这两个范围都是空的。
  • @mudasobwa 错误,它们不被处理a[-2..0] slices 数组相同,在 a.size 内具有非空范围 [-2, -1, 0]界限。
  • @DavidUnric 您能否提供一个不完全是两个元素的数组的生动示例,其中应用a[-2..-3]=SMTH 的结果与a[-2..0]=SMTH 不同?如果不是,请考虑他们被同等对待。我所说的“范围是空的”(虽然不是很清楚)是指“应用Array#[] 的结果是空的”。
猜你喜欢
  • 2020-09-09
  • 2017-12-11
  • 1970-01-01
  • 1970-01-01
  • 2015-11-26
  • 2017-05-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多