2015-12-29 2 views
0

Я хочу совместить пары символов в строке. Предположим, что строка: «zttabcgqztwdegqf». Оба «zt» и «gq» соответствуют парам символов в строке.Ruby ищет строку для совпадения пар символов

Следующий код находит «ZT» соответствие пару, но не «GQ» пара:

#!/usr/bin/env ruby 
string = "zttabcgqztwdegqf" 
puts string.scan(/.{1,2}/).detect{ |c| string.count(c) > 1 } 

код обеспечивает совпадающие пары, где индексы пары 0 & 1,2 & 3, 4 & 5 ... но не 1 & 2,3 & 4,5 & 6, и т.д.:

zt 
ta 
bc 
gq 
zt 
wd 
eg 
qf 

Я не уверен, что регулярное выражение в Ruby, это лучший способ пойти. Но я хочу использовать Ruby для решения.

+0

Я не уверен, что понял вопрос, который я только что ответил. :-). Название относится к «паре совпадающих символов». Не могли бы вы определить, что (с редактированием)? Кроме того, ваш желаемый результат просто представляет собой массив '[" zt "," ta "," bc "," gq "," zt "," wd "," eg "," qf "]' (который представляет собой каждую пару смежные строки соединены)? –

+0

Предположим, что строка была «ttabcttttdefttbcbcbc». Каким будет ваш желаемый результат? –

+0

@CarySwoveland: если я правильно понимаю, он хочет найти каждую пару символов (также перекрывающиеся), которые повторяются внутри строки, его проблема связана с двигателем регулярного выражения, потребляющим символы два раза в раз, поэтому нечетные пары не извлекаются , –

ответ

3

Вы можете сделать свой поиск с одним регулярным выражением:

puts string.scan(/(?=(.{2}).*\1)/) 

regex101 demo

Выходной

ZT
GQ

Regex Breakout

(?=  # Start a lookahead 
    (.{2}) # Search any couple of char and group it in \1 
    .*\1 # Search ahead in the string for another \1 to validate 
)   # Close lookahead 

Примечание

Собираем все проверки внутри опережающего просмотра обеспечить регулярное выражение двигатель не потребляет пару, когда проверяет его. Таким образом, он также работает с перекрывающимися парами, как в строке abcabc: выход будет правильно ab, bc.

Oddity

Если движок регулярных выражений не израсходовал символов, как он может достичь конца строки?

Внутренне после проверки Onigmo (рубиновый двигатель с регулярным выражением) делает один шаг дальше автоматически. Большинство ароматизаторов регулярных выражений ведут себя таким образом, но, например, движку javascript требуется программист, чтобы увеличить индекс последнего совпадения вручную.

+1

Вопрос ужасный. Я неоднократно читал ваш ответ и понимал этот вопрос. – sawa

+0

@CarySwoveland: я обновил ответ, чтобы удалить недостаток, спасибо за обзор –

+0

Очень приятно, лучше, чем я придумал. –

1
str = "ztcabcgqzttwtcdegqf" 

r =/
    (.) # match any character in capture group 1 
    (?= # begin a positive lookahead 
    (.) # match any character in capture group 2 
    .+ # match >= 1 characters 
    \1 # match capture group 1 
    \2 # match capture group 2 
    ) # close positive lookahead 
    /x # extended/free-spacing regex definition mode 

str.scan(r).map(&:join) 
    #=> ["zt", "tc", "gq"] 
0

Вот один из способов сделать это без использования регулярных выражений:

string = "zttabcgqztwdegqf" 
p string.split('').each_cons(2).map(&:join).select {|i| string.scan(i).size > 1 }.uniq 
#=> ["zt", "gq"] 
Смежные вопросы