Разделить строку с несколькими разделителями в Ruby
Возьмем, например, у меня строка вроде этого:
options = "Cake or pie, ice cream, or pudding"
Я хочу иметь возможность разделить строку с помощью or
, ,
и , or
.
Дело в том, что я смог это сделать, но только сначала проанализировав ,
и , or
, а затем разделив каждый элемент массива на or
, затем сглаживая результирующий массив следующим образом:
options = options.split(/(?:\s?or\s)*([^,]+)(?:,\s*)*/).reject(&:empty?);
options.each_index {|index| options[index] = options[index].sub("?","").split(" or "); }
Результирующий массив как таковой: ["Cake", "pie", "ice cream", "pudding"]
Есть ли более эффективный (или более простой) способ разделить мою строку на эти три разделителя?
Ответы
Ответ 1
Как насчет следующего:
options.gsub(/ or /i, ",").split(",").map(&:strip).reject(&:empty?)
- заменяет все разделители, но
,
- разбивает его на
,
- обрезает каждого символа, так как материал типа
ice cream
с ведущим пространством может быть оставлен
- удаляет все пустые строки
Ответ 2
Прежде всего, ваш метод может быть немного упрощен с помощью Array#flatten
:
>> options.split(',').map{|x|x.split 'or'}.flatten.map(&:strip).reject(&:empty?)
=> ["Cake", "pie", "ice cream", "pudding"]
Я бы предпочел использовать одно регулярное выражение:
>> options.split /\s*, or\s+|\s*,\s*|\s+or\s+/
=> ["Cake", "pie", "ice cream", "pudding"]
Вы можете использовать |
в регулярном выражении, чтобы дать альтернативы, а put , or
сначала гарантирует, что он не произведет пустой элемент. Захват пробела с регулярным выражением, вероятно, лучше всего подходит для эффективности, так как вам не нужно снова сканировать массив.
Как указывает Забба, вы все равно можете отклонить пустые элементы, предложив это решение:
>> options.split(/,|\sor\s/).map(&:strip).reject(&:empty?)
=> ["Cake", "pie", "ice cream", "pudding"]
Ответ 3
Как "or"
и ","
делает то же самое, лучший подход заключается в том, чтобы сообщить регулярному выражению, что несколько случаев следует рассматривать так же, как один случай:
options = "Cake or pie, ice cream, or pudding"
regex = /(?:\s*(?:,|or)\s*)+/
options.split(regex)