2014-09-28 2 views
0

Это мой первый вопрос (хотя в прошлом я нашел много отличных решений для квестов в Stack Overflow - это мой первый источник помощи).Может ли кто-нибудь помочь мне сушить этот REGEX?

У меня есть текстовые строки, содержащие месяц и серию дат. Иногда в строке есть два месяца.

date1 = "January 9, 10, 15, 16, 17, 18, 22, 23, 24" 
date2 = "September 19, 20, 25, 26, 27, 28, October 2, 3, 4, 10, 11" 

Я написал очень модный код, который тянет месяц со строки и добавляет каждую дату, плюс год. Однако есть несколько вопросов, которые я просто не могу понять.

  1. Перебор ДАТ: Я знаю, что я должен использовать каждый метод итераций по датам. Я попытался, но я не могу заставить это работать, поэтому я делаю это сложным путем, объединяя месяц с каждым элементом даты. Очевидная проблема заключается в том, что я не знаю, сколько дат будет, поэтому мне нужно построить до самой длинной строки и использовать оператор IF, чтобы определить, достиг ли я конца строки. Я должен использовать date1.length = x plus DO EACH, но я не могу заставить его работать.

  2. КОНКАТЕНТИРОВАТЬ ДЕНЬ МЕСЯЦА ДЕНЬ: мой очень плохой мокрый код работает до тех пор, пока вы не держите monrg день и год вместе, но как мне избавиться от скобок и цитат?

  3. МНОЖЕСТВЕННЫЕ МЕСЯЦЫ: Как выбрать второй месяц в строке и объединить ТОЛЬКО отдельные даты, следующие за именем месяца, чтобы получить MONTH/DD/YY?

Вот пример моего очень плохого кода.

require 'rubygems' 
require 'nokogiri' 
require 'open-uri' 

date1 = "January 9, 10, 15, 16, 17, 18, 22, 23, 24" 
date2 = "September 19, 20, 25, 26, 27, 28, October 2, 3, 4, 10, 11" 
datetext = date1.scan(/([\w\-]+)/)  #=> pulls the whole string 
datetext2 = date1.scan(/(\w*)\s?/)[0] #=> this pulls the month 
datenumbers = date1.scan(/(\d+)/) 
firstdate = datenumbers[0]    #=>ithe first date following the first month 
seconddate = datenumbers[1] 
year = "2014" 

mdy1 = "#{datetext2} #{firstdate} #{year}" 
mdy2 = "#{datetext2} #{seconddate} #{year}" 

puts date1 
puts " " 
puts datetext2 #=> this variable adds the [0] delimiter to pull the 1st month 
puts firstdate 
puts " " 
puts mdy1 
puts mdy2 
puts " " 
+1

Гэри, вот несколько предложений о написании вопросов: 1. устранить все посторонние заявления (например, здесь три запроса 'require'); 2. Когда вы приводите пример (примеры хороши), всегда показывайте желаемый результат и, если применимо, неправильный результат, который вы получаете. –

ответ

0

Предлагаю вам сделать следующее.

код

def extract_dates_by_month(str) 
    str.scan(/[A-Z][a-z]+|\d+/).each_with_object([]) { |e,b| 
    e[0][/[A-Z]/] ? b << [e,[]] : b.last.last << e } 
end 

Пример

str = "September 19, 20, 25, 26, October 2, 3, 4, 10, November 3, 12, 17" 
extract_dates_by_month(str) 
    #=> [["September", ["19", "20", "25", "26"]], 
    # ["October", ["2", "3", "4", "10"]], 
    # ["November", ["3", "12", "17"]]] 

Объяснение

Первый шаг извлечения названия месяцев и дней:

a = str.scan(/[A-Z][a-z]+|\d+/) 
    #=> ["September", "19", "20", "25", "26", "October", "2", "3", "4", "10", 
    # "November", "3", "12", "17"] 

Затем мы разделим этот массив вверх в месяцы:

a.each_with_object([]) { |e,b| e[0][/[A-Z]/] ? b << [e,[]] : b.last.last << e } 
    #=> [["September", ["19", "20", "25", "26"]], 
    # ["October", ["2", "3", "4", "10"]], 
    # ["November", ["3", "12", "17"]]] 

Enumerable#each_with_object создает первоначально пустой массив для переменного блока b и массив, возвращаемый методом. Каждый элемент a передается в блок и ссылается на переменную блока e. Выполняются следующие операции:

b = [] 
e = "September" 
e[0][/[A-Z]/] #=> "S" 
b << [e,[]] #=> [["September", []]] 

e = "19" 
e[0][/[A-Z]/] #=> nil 
b.last.last << e 
b    #=> [["September", ["19"]]] 

e = "20" 
e[0][/[A-Z]/] #=> nil 
b.last.last << e 
b    #=> [["September", ["19", "20"]]] 

e = "25" 
e[0][/[A-Z]/] #=> nil 
b.last.last << e 
b    #=> [["September", ["19", "20", "25"]]] 

e = "26" 
e[0][/[A-Z]/] #=> nil 
b.last.last << e 
b    #=> [["September", ["19", "20", "25", "26"]]] 

e = "October" 
e[0][/[A-Z]/] #=> "O" 
b << [e,[]] #=> [["September", ["19", "20", "25", "26"]], ["October", []]] 

и так далее.

Если вы хотите дни быть целыми числами, замена:

b.last.last << e 

к:

b.last.last << e.to_i 
+0

Спасибо за советы по написанию вопросов и особенно за то, что я сделал шаг за шагом, хотя то, что вы сделали, Кэри. Я попробую ваши предложения и дам вам знать, как это происходит. – Gary7

+0

О, вы спросили меня, каков желаемый результат. Я хочу собрать каждую строку в датах, с которыми я могу работать с использованием Time.parse и strftime. Итак, для «a» я хотел бы в конечном итоге «19 сентября 2014 года, 20 сентября 2014 года, 25 сентября 2014 года, 26 сентября 2014 года, 2 октября 2014 года и т. Д. Затем я буду использовать strftime для получения Дня (т. е. в субботу, 20 сентября 2014 г. и т. д.). – Gary7

+0

ОБНОВЛЕНИЕ - после работы с регулярным выражением, предоставленным Кэри на некоторое время (спасибо!), я понял, что он удаляет последнюю дату в строке при запуске это в коде IRB. Вот код, который я запускаю и вывод. Может ли кто-нибудь сказать мне, почему это происходит? – Gary7

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