有人可以解释为什么Ruby中的.split方法以这种方式工作吗?

时间:2017-01-03 17:19:44

标签: ruby-on-rails ruby split

为什么.split在其参数是字符串的第一个字母时创建一个空字符,并且当参数是字符串的最后一个字母时它不会这样做?在第二个例子中,没有"说",因为我右边没有任何东西我会输出"" ? (字符串末尾是否有' nil')

我知道这不是一个非常相关的问题,但是,我想了解该方法为什么会这样。谢谢!

string = "aware"
string.split("a") --> # outputs: ["", "w", "re"]
string.split("e") --> # outputs: ["awar"]

2 个答案:

答案 0 :(得分:1)

以下是String#split可能具有的行为异常的简单示例:

"1234".split(/1/) # => ["", "234"]

上面例子的预期结果似乎是[“234”]因为它在1上分裂,而是我们得到一个意外的空字符串。 **

  

String#split如何工作

** 内部String#split仅使用正则表达式分隔符。如果传入字符串分隔符,它将被转义为正则表达式,然后变为正则表达式:

1 2 3 4
 "1234".split("1") # is really the same as "1234".split( Regexp.new( Regexp.escape("1") ) )

对于本文的其余部分,当我引用分隔符时,我指的是正则表达式分隔符,因为内部是String#split使用的。 String#split跟踪五条重要信息的跟踪:

  • 字符串本身

    返回的结果数组

    位置标记从哪里开始匹配字符串 分隔符。这是起始位置,初始化为0。

    字符串与分隔符匹配的位置标记。这是 匹配的位置并初始化为0.

    标记紧随其后的偏移的位置 字符串与分隔符匹配

String#split在循环中运行。它继续匹配字符串与分隔符,直到找不到更多匹配项。它在每次迭代时执行以下步骤:

  • 从起始位置匹配字符串
  • 的分隔符
  • 将匹配位置设置为分隔符与字符串匹配的位置
  • 如果分隔符与字符串不匹配则打破循环
  • 使用the的起始位置和匹配位置创建子字符串 字符串匹配。将此子字符串推送到结果数组
  • 设置下一次迭代的开始位置

通过这些知识,让我们讨论String#split如何处理前面的例子:

"1234".split(/1/) # => ["", "234"]
  • 第一个循环
  • 将起始位置初始化为0
  • 分隔符与字符串“1234”
  • 匹配
  • 第一个匹配发生在第一个字符“1”,即at 位置0.这将匹配的位置设置为0。
  • 使用起始位置和匹配位置创建子字符串 推到我们的结果数组。这给了我们字符串[start,end] 转换为“1234”[0,0],返回空字符串。
  • 开始位置重置为位置1
  • 第二个循环
  • start现在是1
  • 分隔符与字符串的剩余部分“234”
  • 匹配
  • 找不到匹配项,因此循环结束。
  • 使用起始位置和剩余部分创建子字符串 字符串并推送到结果数组
  • 返回结果数组

鉴于String#split如何工作,很容易理解为什么我们在结果数组中有意外的空字符串。您应该注意到这只是因为正则表达式在第一个字符处匹配我们的字符串。下面是一个示例,其中分隔符与第一个字符不匹配,并且没有空字符串:

"1234".split(/2/) # => ["1", "34"]

答案 1 :(得分:0)

镐书上写着字符串#split

如果省略limit参数,则禁止尾随空字段。 ...如果为负数,则返回的字段数没有限制,并且不会抑制尾随空[空]字段。所以:

irb(main):001:0> "aware".split('e')
=> ["awar"]
irb(main):002:0> "aware".split('e',-1)
=> ["awar", ""]