2016-07-22 103 views
0

在Ruby中,以下列方式拆分字符串的最简单方法是什么?红宝石拆分字符串和保存分隔符

  • 'abc+def'应该拆分['abc', '+', 'def']

  • 'abc\*def+eee'应该拆分['abc', '\*', 'def', '+', 'eee']

  • 'ab/cd*de+df'应该拆分['ab', '/', 'cd', '\*', 'de', '+', 'df']

的想法是分裂有关这些符号的字符串: ['-', '+', '*', '/']并将结果中的这些符号保存在适当的位置。

+0

提示:'.split'接受正则表达式 –

+0

欢迎使用Stack Overflow。请阅读“[问]”和链接的页面。我们需要看到你解决问题的努力的证据。你写代码了吗?如果不是,为什么不呢?你在哪里寻找解决方案?如果你没有搜索,为什么?目前,您的问题看起来像是我们为您编写代码的请求,这不是您的问题。 –

+0

@theTinMan对不起,关于这个。我将在未来提出问题时记住这一点。 – Lokesh

回答

10

选项1

/\b/word boundary并且它具有零宽度,所以不会消耗任何字符

'abc+def'.split(/\b/) 
# => ["abc", "+", "def"] 

'abc*def+eee'.split(/\b/) 
# => ["abc", "*", "def", "+", "eee"] 

'ab/cd*de+df'.split(/\b/) 
# => ["ab", "/", "cd", "*", "de", "+", "df"] 

选项2

如果您的字符串包含其他字边界字符,你只需要t o分割为-,+,*/,则可以使用capture groups。如果使用捕获组,则String#split也将在结果中包含捕获的字符串。 (感谢指出这@Jordan)(@Cary Swoveland对不起,我没有看到你的答案时,我做了这个编辑)

'abc+def'.split /([+*\/-])/ 
# => ["abc", "+", "def"] 

'abc*def+eee'.split /([+*\/-])/ 
# => ["abc", "*", "def", "+", "eee"] 

'ab/cd*de+df'.split /([+*\/-])/ 
# => ["ab", "/", "cd", "*", "de", "+", "df"] 

选项3

最后,对于那些使用语言可能不支持字符串与捕获组分开,您可以使用两个lookarounds。 Lookarounds也是零宽度匹配,所以他们不会消耗任何字符

'abc+def'.split /(?=[+*\/-])|(?<=[+*\/-])/ 
# => ["abc", "+", "def"] 

'abc*def+eee'.split /(?=[+*\/-])|(?<=[+*\/-])/ 
# => ["abc", "*", "def", "+", "eee"] 

'ab/cd*de+df'.split /(?=[+*\/-])|(?<=[+*\/-])/ 
# => ["ab", "/", "cd", "*", "de", "+", "df"] 

这里的想法是拆就由您隔板的一个之前的任何字符,或后跟的一个任意字符分隔符。让我们做一个小的视觉

ab ⍿/⍿ cd ⍿ * ⍿ de ⍿ + ⍿ df

符号无论之前或之后的分离器之一。所以这是字符串将被切断的地方。


选项4

也许你的语言没有一个字符串split功能或明智的方式使用正则表达式进行互动。很高兴知道您不必坐下来猜测是否有巧妙的内置程序可以神奇地解决您的问题。有几乎总是使用基本的说明

class String 
    def head 
    self[0] 
    end 
    def tail 
    self[1..-1] 
    end 
    def reduce acc, &f 
    if empty? 
     acc 
    else 
     tail.reduce yield(acc, head), &f 
    end 
    end 
    def separate chars 
    res, acc = reduce [[], ''] do |(res, acc), char| 
     if chars.include? char 
     [res + [acc, char], ''] 
     else 
     [res, acc + char] 
     end 
    end 
    res + [acc]  
    end 
end 

'abc+def'.separate %w(- +/*) 
# => ["abc", "+", "def"] 

'abc*def+eee'.separate %w(- +/*) 
# => ["abc", "*", "def", "+", "eee"] 

'ab/cd*de+df'.separate %w(- +/*) 
# => ["ab", "/", "cd", "*", "de", "+", "df"] 
+0

太棒了!特别是周围的环境。非常感谢。干杯! – Lokesh

+0

太好了。 – Lokesh

+0

查找过度。 'String#split'会保存捕获,所以你只需要'string.split /([+ * \/- ])/'。 –

2

我看到这是近@ naomic的一部分答案来解决问题的方式,但我会离开它的小的差异。

splitters = ['-', '+', '*', '/'] 

r = /(#{ Regexp.union(splitters) })/ 
    # => /((?-mix:\-|\+|\*|\/))/ 

'abc+def'.split r 
    #=> ["abc", "+", "def"] 
"abc\*def+eee".split r 
    #=> ["abc", "*", "def", "+", "eee"] 
'ab/cd*de+df'.split r 
    #=> ["ab", "/", "cd", "*", "de", "+", "df"] 

注:

  • 正则表达式的地方#{ Regexp.union(splitters) }在捕获组,导致String#split包括那些分裂(第三段最后一句)的字符串。
  • 第二个示例字符串必须用双引号才能转义*
+0

不错使用'Regexp.union'。很高兴我了解到'String#split'允许使用捕获组。我从来不知道^ _ ^ – naomik