2016-08-19 4 views
0

Я работаю над проблемой, которая включает в себя разделение строки на каждую группу символов.Ruby Split string при разнице символов с использованием regex

Например,

"111223334456777" #=> ['111','22','333','44','5','6','777'] 

Как я сейчас делаю это сейчас использует перечислитель и сравнивая каждый символ с следующей, и разделив массив, который путь.

res = [] 
str = "111223334456777" 
group = str[0] 
(1...str.length).each do |i| 
    if str[i] != str[i-1] 
    res << group 
    group = str[i] 
    else 
    group << str[i] 
    end 
end 
res << group 
res #=> ['111','22','333','44','5','6','777'] 

Я хочу посмотреть, могу ли я использовать регулярное выражение для этого, что сделает этот процесс намного проще. Я понимаю, что я мог бы просто поместить этот блок кода в метод, но мне любопытно, можно ли здесь использовать regex.

Так что я хочу сделать, это

str.split(/some regex/) 

для получения того же результата. Я думал о положительном взгляде, но я не могу понять, как заставить регулярное выражение распознать, что персонаж отличается.

Есть ли у кого-нибудь идеи, если это возможно?

+0

Это не отвечает на ваш вопрос, но вы можете написать '' 111223334456777 ".each_char.slice_when {| a, b | a! = b} .map (&: join) # => ["111", "22", "333", "44", "5", "6", "777"] '. –

+0

@CarySwoveland, вы код, безусловно, чище, чем мой, я просто написал это, чтобы уточнить, что я искал. – davidhu2000

+0

В соответствии с комментарием Штефана о ответе Тадмана выше можно упростить «111223334456777» .each_char.slice_when (&:! =). Map (&: join) '. –

ответ

4
str = "111333224456777" 

str.scan /0+|1+|2+|3+|4+|5+|6+|7+|8+|9+/ 
    #=> ["111", "333", "22", "44", "5", "6", "777"] 

или

str.scan(/((\d)\2*)/).map(&:first) 
    #=> ["111", "333", "22", "44", "5", "6", "777"] 

Читатели: могут последним быть упрощена?

+0

второй способ совершенный, только то, что я ищу. Спасибо. – davidhu2000

+1

'str.chars.chunk_while {| b, a | b == a} .map (&: join) 'также работает и на произвольном входе, возможно, включая буквы и т. д. – tadman

3

chunk_while метод это то, что вы ищете здесь:

str.chars.chunk_while { |b,a| b == a }.map(&:join) 

Это сломается что-нибудь, где текущий символ a не соответствует предыдущему символу b. Если вы хотите ограничить только цифры, вы можете выполнить предварительную обработку.

В Enumerable есть много очень удобных методов, которые стоит изучить, и каждая новая версия Ruby, кажется, добавляет больше их.

+1

Может быть сокращено до 'str.chars.chunk_while (&: ==). Map (&: join)' – Stefan

+1

... или 'str.each_char.chunk_while (&: ==). Map (&: join)' чтобы избежать создания временного массива 'str.chars'. –

1

Другая опция, которая использует метод group_by, который возвращает хеш с каждым отдельным номером в качестве ключа и массив сгруппированных чисел в качестве значения.

"111223334456777".split('').group_by { |i| i }.values.map(&:join) => => ["111", "22", "333", "44", "5", "6", "777"] 

Хотя он не реализует регулярное выражение, кто-то может найти его полезным.

+0

Обратите внимание, что это возвращает '[" 11 "," 22 "," 33 "]' для '" 123123 "' – Stefan