Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Match sequences of consecutive characters in a string

Tags:

regex

ruby

I have the string "111221" and want to match all sets of consecutive equal integers: ["111", "22", "1"].

I know that there is a special regex thingy to do that but I can't remember and I'm terrible at Googling.

like image 486
itdoesntwork Avatar asked Dec 14 '11 01:12

itdoesntwork


People also ask

What is a series of consecutive characters within a string?

What is a series of consecutive characters within a string? Substring/Slice. A sequence of consecutive characters from the string. Concatenation.

How do you find consecutive repeated characters in a string in SQL?

How do you find consecutive repeated characters in a string in SQL? (assuming your string is located in the column named my_string of a single-row table named my_table ). In Oracle, you'll need the scalar function INSTR(my_string, 'AA') . In SQL Server, you'll need CHARINDEX('AA', my_string) .

Does * match everything in regex?

Throw in an * (asterisk), and it will match everything. Read more. \s (whitespace metacharacter) will match any whitespace character (space; tab; line break; ...), and \S (opposite of \s ) will match anything that is not a whitespace character.


1 Answers

Using regex in Ruby 1.8.7+:

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

This works because (\d) captures any digit, and then \2* captures zero-or-more of whatever that group (the second opening parenthesis) matched. The outer (…) is needed to capture the entire match as a result in scan. Finally, scan alone returns:

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

…so we need to run through and keep just the first item in each array. In Ruby 1.8.6+ (which doesn't have Symbol#to_proc for convenience):

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

With no Regex, here's a fun one (matching any char) that works in Ruby 1.9.2:

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

Here's another version that should work even in 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"]
like image 163
Phrogz Avatar answered Nov 12 '22 20:11

Phrogz