【问题标题】:Why does s[n..-1] work in ruby?为什么 s[n..-1] 在红宝石中工作?
【发布时间】:2012-03-20 05:39:12
【问题描述】:

我对红宝石还很陌生。最近想从字符串的第n个字符到结尾提取一部分字符串。

像 s[n,(s.size - n)] 这样的操作对我来说似乎很不雅,所以我问了几个朋友。

有人建议我尝试 s[n..-1],果然可行,但他无法给我一个很好的理由为什么它应该有效。我发现它的工作原理相当令人费解,正如 irb1.9 的以下输出应该解释的那样:


> s = "0123456789"
=> "0123456789"
> s[2..-1]
=> "23456789"
> (2..-1).to_a
=> []

如您所见,范围对象 2..-1 是空的——它没有成员,如果您将值从 2 上升到 -1,这绝对是您所期望的。这与范围对象应如何工作的文档一致。

使用范围索引字符串的文档清楚地说明:“如果给定范围,则返回包含范围给定偏移量处的字符的子字符串”——但这是一个空集。

我也无法在“The Ruby Programming Language”或 Ruby 文档中找到使用s[n..-1] 等对字符串进行索引的示例,并且在其他官方来源中也找不到此类示例。然而,这似乎是民间传说,即使手册中没有任何内容表明您可以通过这种方式索引具有范围的字符串,并且即使该范围没有成员,也可以获得您得到的结果。

然而,我的朋友是对的,它有效。

那么,有人可以解释一下为什么这对我有用吗?我也很想知道它的工作原理是否是 MRI/YARV 的侥幸,或者这是否绝对有望在所有 Ruby 实现中工作,如果是这样,它在哪里可以工作?

编辑添加:

下面的回答者声称只有范围的 beginend 属性对这些目的很重要,但我在 TRPL 或 Ruby 文档中找不到任何文档。答案还声称确实存在这种“混合符号”范围索引的示例,但我能找到的唯一一个是在混合范围索引显示产生nil,而不是字符串切片的上下文中.因此,我觉得这个答案并不令人满意。

编辑添加:

看来正确的答案是,这确实是 Ruby 文档中的一个缺陷。

编辑添加:

该错误已由 Ruby 文档团队修复:请参阅 https://bugs.ruby-lang.org/issues/6106

【问题讨论】:

  • Array#[] 是一种方法。谷歌搜索 ruby string []ruby string#[] 将引导您找到文档作为最佳结果。
  • 抱歉,没有。这是不正确的。我已经阅读了该文档。您需要更仔细地重新阅读问题。
  • a[-3,2] #=> "er" a[-4..-2] #=> "her" a[12..-1] #=> nil a[ -2..-4] #=> "" (引用自文档)
  • 你又误会了。我很清楚您引用的文档部分,它不是一个反例。请在发表评论之前阅读整个讨论,包括以下所有内容。请注意,您在上面引用的唯一与文档相关的示例是 a[12..-1] #=> nil 并且产生 nil 而不是字符串切片——文档中不存在我所说的示例,是的,我我确定。
  • +1 我以前从未想过这个。

标签: ruby


【解决方案1】:

你说得对,n..-1 的范围是空的。不过这并不重要,因为String#[] 不会将范围视为一个集合——它只是使用范围的beginend 属性。

关于文档:The rdoc documentation of String#[] 列出了 String#[] 对于每种可能类型的参数(包括带负数的范围)的行为以及示例。所以你不必依赖民间传说。相关引述:

如果给定一个范围,则返回一个子字符串,该子字符串包含该范围给定的偏移量处的字符。 [...] 如果偏移量为负,则从 str 的末尾开始计算。 [...]

a = "hello there"
# ...
a[-4..-2]              #=> "her"

【讨论】:

  • 但是只有 beginend 重要的记录在哪里?此外,关于偏移量的部分并没有明确告诉我们空范围对象是可以的,因为beginend 属性都很重要,并且在任何文档中都没有给出这种混合符号索引的示例。已经看到。请注意,上面的a[12..-1] 在上下文中生成nil,而不是数组的一部分。
  • 您编辑了上面的示例以删除产生nila[12..-1] 示例而不是数组切片。据我所知,您的说法并不正确:文档中没有“所有可能的论点”,为此,一个确实必须依赖民间传说。
  • @Perry 它产生了nil,因为12 超出了给定字符串的范围。请注意,-4 .. -2 也是一个空范围,因此该示例向您展示了空范围不是问题(如果是的话,使用负索引的范围将永远无法工作)。
  • 是的,准确地说,它产生了nil,但是为什么它产生 nil 完全是模棱两可的。 -4..-2 不是一个空范围——你完全错了。试试 (-4..-2).to_a
  • @Perry 不同意某人和/或告诉他们他们错了,这很酷,但反复告诉他们“让其他人回答问题”,这让我觉得这是一种糟糕的方法。
【解决方案2】:

这是文档中的错误。

自从 Pickaxe 书像流星一样降落在 matz 真正正确和全面的 HTML 文档上之后,Ruby 的文档就很糟糕。这是一个有时仍然让我恼火的话题。您的问题的答案,来自 1.4link

自我[nth]

从数组中检索第 n 项。索引从零开始。如果 index 为负数,则从数组末尾向后计数。最后一个元素的索引是-1。如果数组中不存在第 n 个元素,则返回 nil。

自我[开始..结束]

返回一个数组,该数组包含从头到尾的对象,包括两端。如果使用 ...(而不是 ..),则不包括 end。如果 end 大于数组的长度,它将被四舍五入到长度。如果 start 超出数组范围,则返回 nil。如果 start 大于 end with 在数组范围内,则返回空数组([])。

-1 是定义为数组的最后一个索引,为方便起见。

【讨论】:

  • 好的,所以这曾经被记录在案,现在已成为民间传说的一部分,因为文件目前没有提到它——我说得对吗?
  • (以及如何提交一份关于此的错误报告......我无法弄清楚。)
  • @Perry,当然。就像this,我想。
  • 一个更好的链接应该是bugs.ruby-lang.org -- 我现在已经提交了一个错误报告。
  • @Perry 是的,我想我没有这样做——正索引从字符串的开头开始,负索引从结尾开始,如记录所示。我真的不明白具有混合符号的开始/结束索引如何改变。
猜你喜欢
  • 1970-01-01
  • 2012-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-13
  • 1970-01-01
  • 2013-10-17
相关资源
最近更新 更多