在一个字符串中匹配连续字符序列

7
我有一个字符串"111221",想匹配所有连续相等的整数集:["111", "22", "1"]
我知道有一种特殊的正则表达式可以做到这一点,但我不记得它是什么,而且我很不擅长谷歌搜索。

1
当输入包含非数字字符时,例如“111aaa222”和“111aaa111”,应该发生什么? - Phrogz
4个回答

13

在Ruby 1.8.7+中使用正则表达式:

p s.scan(/((\d)\2*)/).map(&:first)
#=> ["111", "22", "1"]

这能够正常工作是因为(\d)匹配任何数字,然后\2*匹配零个或多个与该组(第二个括号)匹配的内容。外部的(...)需要捕获整个匹配结果以便在scan中返回。最后,仅调用scan就可以返回:

[["111", "1"], ["22", "2"], ["1", "1"]]

我们需要遍历并仅保留每个数组中的第一项。在Ruby 1.8.6+中(不方便使用Symbol#to_proc):

p s.scan(/((\d)\2*)/).map{ |x| x.first }
#=> ["111", "22", "1"]

没有使用正则表达式,这是一个有趣的方法(匹配任何字符),适用于Ruby 1.9.2:

p s.chars.chunk{|c|c}.map{ |n,a| a.join }
#=> ["111", "22", "1"]

这里有另一个版本,甚至可以在Ruby 1.8.6中使用:

p s.scan(/./).inject([]){|a,c| (a.last && a.last[0]==c[0] ? a.last : a)<<c; a }
# => ["111", "22", "1"]

1
你的“fun one”将匹配“00aa00”作为[“000000”] - 在示例输入上工作,但在任何非平凡的示例上都不起作用。 - klochner

0
我发现这个方法可行,它首先匹配一个组中的每个字符,然后匹配在其后的任何相同字符。这将导致一个由两个元素数组组成的数组,每个数组的第一个元素是初始匹配,第二个元素是与第一个字符匹配的任何其他重复字符。这些数组被合并在一起,以获得一个重复字符的数组:
input = "WWBWWWWBBBWWWWWWWB3333!!!!"
repeated_chars = input.scan(/(.)(\1*)/)
# => [["W", "W"], ["B", ""], ["W", "WWW"], ["B", "BB"], ["W", "WWWWWW"], ["B", ""], ["3", "333"], ["!", "!!!"]]
repeated_chars.map(&:join)
# => ["WW", "B", "WWWW", "BBB", "WWWWWWW", "B", "3333", "!!!!"]

作为替代方案,我发现可以创建一个新的Regexp对象来匹配输入字符串中每个唯一字符的一个或多个出现,如下所示:
input = "WWBWWWWBBBWWWWWWWB3333!!!!"
regexp = Regexp.new("#{input.chars.uniq.join("+|")}+")
#=> regexp created for this example will look like: /W+|B+|3+|!+/

然后将该Regex对象用作scan的参数,以拆分所有重复字符,如下所示:

input.scan(regexp)
# => ["WW", "B", "WWWW", "BBB", "WWWWWWW", "B", "3333", "!!!!"]

0
"111221".gsub(/(.)(\1)*/).to_a
  #=> ["111", "22", "1"]

这里使用的是String#gsub的形式,它没有块,因此返回一个枚举器。看起来gsub在v2.0中被赋予了该选项。


-2

你可以尝试的是

string str ="111221";
string pattern =@"(\d)(\1)+";

希望能对你有所帮助


1
因为a)这不起作用(您需要使用*而不是+),b)这不是Ruby语法,甚至不能直接在Ruby中工作,所以被踩了。 - Phrogz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接