2014-12-29 3 views
0

Мне нужно вынуть самую длинную подстроку символов с верхним регистром. Таким образом, из строки:Поиск подстроки с верхним регистром

"aaBBBBcBBdDDD" 

Мне нужно получить "BBBB".

Есть ли удобный метод Ruby для этого или регулярного выражения? Я пробовал:

string.scan(/[[:upper:]]/) 

и это почти все, только он дает ВСЕ символы капитала, а не самую длинную последовательность.

+1

Это не то, что regex может сделать. (По крайней мере, это не то, что предназначено для регулярного выражения.) –

+0

Как сказал @Rawing, это не то, что для Regexp. Регулярные выражения отлично подходят для поиска вещей, которые * выглядят * как что-то, но они ужасно ищут что-то, что есть именно то, что представлено несколькими вариантами выбора, особенно если есть какая-нибудь комната для маневра. –

ответ

1

Вы не можете найти строку, которая имеет максимальную длину только через регулярные выражения. Вам нужно использовать некоторые встроенные функции Ruby.

> m = "aaBBBBcBBdDDD".scan(/[[:upper:]]+/) 
=> ["BBBB", "BB", "DDD"] 
> vc = m.sort{|a,b| b.size <=> a.size} 
=> ["BBBB", "DDD", "BB"] 
> vc.delete_if{|a| a.size < vc.first.size} 
=> ["BBBB"] 
+0

спасибо, что «+» было тем, что мне не хватало :) – Leo

+0

yep, '+' соответствует предыдущему токену один или несколько раз. –

+0

Что делать, если строка выглядит так: 'aaBBBBAABcBBdDDD'? Он вернет 'BBBBAAB' – hek2mgl

0
([A-Z]+) 

Попробуйте это. Захватите все группы, а максимальная длина - ваш ответ. Смотрите демо.

https://regex101.com/r/gX5qF3/11

+1

хорошее решение только работает только для символов ASCII – Leo

8

Использование регулярных выражений, чтобы получить массив заглавных слов, а затем использовать Enumerable#max_by найти самый длинный:

"aaBBBBcBBdDDD".scan(/[[:upper:]]+/).max_by {|x| x.length} 
# => "BBBB" 

или проще:

"aaBBBBcBBdDDD".scan(/[[:upper:]]+/).max_by(&:length) 
# => "BBBB" 
0

Вы не указали ожидаемый результат для более одной строки той же максимальной длины.

@ Ответ AvinashRaj будет обрабатывать это, в то время как @ YuHao's will not. Если вы хотите только 1 результат, я бы предложил ответить @ YuHao, если вы хотите, чтобы все результаты я изменил. Ответ AvinashRaj на что-то вроде этого.

"aaBBBBcBBdDDDD".scan(/[[:upper:]]+/).tap do |a| 
    max_length = a.map(&:length).max 
    a.delete_if{|x| x.length < max_length } 
end 
#=> ["BBBB","DDDD"] 
+0

Я не думаю, что 'tap' покупает вам что-нибудь здесь. Было бы яснее, чтобы написать: 'a =" aaBBBBcBBdDDD ".scan (/ [[: upper:]] + /); max_length = a.map (&: length) .max; a.select {| s | s.size == max_length} '. –

+0

@ CarySwoveland благодарим вас за ответ. Вероятно, для этого есть еще дюжина просто задуманных вариантов. Я просто не вижу необходимости в нескольких локальных переменных, которые больше не будут использоваться нигде. Бенчмаркинг их показывает не существенную разницу в производительности, либо все они находятся в пределах 10% +/- – engineersmnky

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