2015-11-09 4 views
2

Мне нужно найти все группы из двух смежных слов в строке, но только слова длиной 2-3 символа. До сих пор я пришел с этим:Поиск всех групп смежных слов в строке

'toolong fee fi fo fum toolong verylong aa bb'.scan(/\b[a-z]{2,3}\s+\b[a-z]{2,3}/) 
=> ["fee fi", "fo fum", "aa bb"] 

Но я хочу что-то вроде этого:

=> ["fee fi", "fi fo", "fo fum", "aa bb"] 

Любая помощь с благодарностью.

+1

Downvoter: обратите внимание на комментарий? –

ответ

2

Вам нужно использовать lookahead вместе с группой захвата для выполнения совпадающих совпадений.

> 'toolong fee fi fo fum toolong verylong aa bb'.scan(/(?=\b([a-z]{2,3}\s+[a-z]{2,3})\b)/) 
=> [["fee fi"], ["fi fo"], ["fo fum"], ["aa bb"]] 
> 'toolong fee fi fo fum toolong verylong aa bb'.scan(/\b(?=([a-z]{2,3}\s+[a-z]{2,3})\b)/).flatten 
=> ["fee fi", "fi fo", "fo fum", "aa bb"] 
+1

Небольшое улучшение для перемещения первого '\ b' снаружи. '\ b (? =' ... не нужно смотреть вперёд в каждую позицию. –

+0

Мне это нравится, спасибо! В качестве небольшого упрощения я использовал 'flatten' в конце, а не' map'. –

1

Логический способ потреблять первый 3 LTR слово, то LOOKAHEAD для следующего
.

Поскольку вы хотите, чтобы оба слова были вместе, вы бы захватили каждый из них, а затем присоединитесь к
их вместе после каждого матча. \b([a-z]{2,3})(?=(\s+[a-z]{2,3})\b)

\b 
([a-z]{2,3})    # (1) 
(?= 
     (       # (2 start) 
      \s+ 
      [a-z]{2,3} 
    )        # (2 end) 
     \b 
) 

Следующим логическим способом (хотя, не интуитивно) является LookAhead для
комбинированных 2 слов, а затем потреблять первый, чтобы продвинуть матч
позицию. (?=\b(([a-z]{2,3})\s+[a-z]{2,3})\b)\2

Этот способ позволяет вам просто захватывать группу 1 без необходимости присоединяться.

(?= 
     \b 
     (       # (1 start) 
      ([a-z]{2,3})    # (2) 
      \s+ 
      [a-z]{2,3} 
    )        # (1 end) 
     \b 
) 
\2 
Смежные вопросы