2016-01-26 3 views
1

У меня есть массив строк:точное совпадение заданного числа символов в строке

strings = ['fo','foo','fooo'] 

Какой код я должен написать, чтобы найти строку, которая имеет только oo в нем?

Я попытался следующий код

strings.select!{|string| string.include? 'oo'} 
#=> ['foo','fooo'] 

Однако 'fooo' не то, что я хотел в результирующем массиве, только в этом случае массив с ['foo'] должен быть возвращен.

+1

Вы ошибаетесь. '' foo "' включает в себя не только '' oo "', но также '' f "', '" fo "', '" foo "'. – sawa

ответ

1

Возможно, это?

strings.select { |s| s.count('o') == 2 && /o{2}/ =~ s } 

Edit: Edited правильность на основе комментариев.

+0

Да, спасибо! –

+2

Это решение выберет 'photo', если оно присутствует в массиве' strings'. Это желательно? –

+0

Поскольку это отклоняет «oofoo», я предполагаю, что вы предположили, что в строке может появиться только одна «оо». –

1

Какой код следует писать для того, чтобы найти строку, содержащую только oo?

strings.select{|e| e == "oo"} 
+0

Прошу прощения, строка должна содержать «oo» –

+0

Тогда это то, что вы уже сделали. – sawa

+2

Nadir, sawa интерпретировал ваш вопрос буквально, а именно, что вы хотите найти строку, которая * только * содержит '' oo ", что является еще одним способом сказать, что вы хотите найти * строку *" oo ". Это явно не то, что вы хотите, но это единственный способ, которым ваш вопрос может быть истолкован.Например, '' foodooo ''удовлетворяет вашим требованиям? Вам нужно отредактировать свой вопрос, чтобы уточнить его. Вы должны сделать это, даже если вы выбрали ответ, как многие другие могут прочитать его в будущем. Не изменяйте свой вопрос, просто добавьте его, указав, что это редактирование. –

0

Используйте отрицательные lookarounds ..

> strings.select{ |i| i[/(?<!o)oo(?!o)/] } 
=> ["foo"] 

(?<!o) утверждает, что матч не будет предшествовать o, (?!o) утверждает, что матч не будет сопровождаться o

Для соответствия строке, содержащей ровно 2 o's

strings.select{ |i| i[/^[^o]*oo[^o]*$/] } 
+0

Ваш код выберет '' oofooo''. Это ожидалось? – sawa

+0

не знаю, может быть оп знает. –

+0

У вас должно быть четкое мнение, прежде чем отвечать на любые вопросы. – sawa

1

Вот один из способов сделать это.

strings = ['fo','foo','fooo', 'oofo', 'oofoo', 'oof', 'photo', 'photoo', "hi"] 

s = strings.select do |s| 
    s.chars.each_cons(2).map(&:join).count("oo") == 1 
end 
#=> ["foo", "oofo", "oof", "photoo"] 
1

Чтобы определить, содержит ли строка одной или нескольких строк вида «xooy», где «х» и «у» являются любые другие, чем «о» символов, но не содержит строки «ХОУ» и или "ооо" (и расширением, нет "OOOO" и т.д.), вы можете сделать следующее:

def double_os_only?(str) 
    str.scan(/o+/).map(&:size).minmax == [2,2] 
end 

strings = ['fo','foo','fooo', 'oofo', 'oofoo', 'oofooo', 'photo', 'potatoo', "dang"] 
strings.map { |s| puts "#{ s } => #{ double_os_only?(s) }" } 

fo  => false 
foo  => true 
fooo => false 
oofo => false 
oofoo => true 
oofooo => false 
photo => false 
potatoo => false 
dang => false 

Обратите внимание, что, если str.scan(/o+/) #=> [], [].map(&:size) #=> [] и [].minmax #=> [nil,nil].

Другой способ заключается в изменении регулярное выражение, данное @Avinash:

R =/
    ^   # match beginning of the line 
    (?:   # begin a non-capture group 
     [^o]*  # match zero or more characters other than 'o' 
     oo   # match 'oo' 
     [^o]*  # match zero or more characters other than 'o' 
     (?!o)  # do not match 'o' in a negative lookahead 
    )+   # end the non-capture group and perform >= 1 times 
    $    # match end of line 
    /x   # extended/free-spacing regex definition 

def double_os_only?(str) 
    !!(str =~ R) 
end 

! преобразует truthy значение false и falsy значение true. !! поэтому преобразует истинное значение в true и значение фальши в false.

Смежные вопросы