Ruby数组切片,无法理解这个简单的代码片段

时间:2012-04-15 12:45:27

标签: ruby arrays

  

可能重复:
  Array slicing in Ruby: looking for explanation for illogical behaviour (taken from Rubykoans.com)

我有一个简单的数组对象:

array = [:peanut, :butter, :and, :jelly]

它的长度显然是4!

现在,看看这些陈述:

array[4,0] == []
array[5,0] == nil

从第4个索引切片数组,它返回一个空数组,但是从第5个元素开始,它返回nil。为什么会这样?

3 个答案:

答案 0 :(得分:1)

slice(start, length)(当您访问array[]时调用的方法)从索引length开始返回长度为start的数组。这解释了为什么array[4,0]返回[]

然而,这种方法存在一个极端情况。 The Ruby documentation of slice说:

  

如果索引(或起始索引)超出范围,则返回nil。

在第二个示例中,5超出了array的范围。这会导致该方法返回nil

答案 1 :(得分:1)

有一秒钟,我以为你发现了一个错误,但我想我可以解释这个行为。您提供给slice的起始索引在>该索引处的元素之前仅被视为。因此,索引4被认为是数组的 end (就在索引4之前,就在索引3之后)。以下示例应明确说明:

> [1,2,3,4][0, 3]
 # => [1, 2, 3] 
> [1,2,3,4][1, 3]
 # => [2, 3, 4] 
> [1,2,3,4][2, 3]
 # => [3, 4] 
> [1,2,3,4][3, 3]
 # => [4] 
> [1,2,3,4][4, 3]
 # => [] 
> [1,2,3,4][5, 3]
 # => nil 

答案 2 :(得分:1)

实际上,你发现“奇怪”的东西的原因应该始终在于源代码。我只是从https://github.com/ruby/ruby/blob/trunk/range.c

中选择相关的代码段
...
if (beg < 0) {
beg += len;
if (beg < 0)
    goto out_of_range;
}
if (err == 0 || err == 2) {
if (beg > len)
    goto out_of_range;
if (end > len)
    end = len;
}
...

此处,如果起始索引beg小于-length,则返回范围Qnil。否则,如果起始索引大于数组的长度(代码片段中为len),则它也会返回超出范围(Qnil)。注意这里,它大于不大于或等于,这就是为[]得到array[4,0]的原因(虽然4超出范围)但nilarray[5,0]