Przekształcanie dat w zakresy

Witajcie.
Mam za zadanie napisać kawałek kodu, który po spełnieniu pewnych warunków połączy mi daty w zakresy.
ogólnie tak to mniej więcej powinno wyglądać:

dates = ["28-10-2010", "29-10-2010", "1-11-2010", "3-11-2010"] @output = {:bar => [], :not_bar => []} dates.each do |date| if Foo.bar?(date) # (...) end end @output.inspect # => { :bar => ["28-10-2010 - 1-11-2010", "3-11-2010"], :not_bar => [] }
szczerze mówiąc, nie mam pomysłu na kod, który byłby ruby-way i rozwiązywał ten problem…
Żeby nie było, że jestem leniem, liczę na gotowca, to wstawiam taki pseudokod, nad którym myślałem:

if date.wday+1 == next_date.wday || (date.wday == 5 && next_date.wday == 1 ) @output[:bar] << "#{date} - #{next_date}" else @output[:bar] << date end
z tym, że rozwiązuje on problem tylko dwóch dni.

Byłbym bardzo wdzięczny za wszelkie podpowiedzi :wink:

Nie wiem, czy o to dokładnie chodzi, ale rozwiązanie wydaje się proste - posortuj daty, a potem zastosuj swoje rozwiązanie dla kolejnych par (choć nie wiem, skąd się tam bierze wday, bo nic o tym nie piszesz w warunkach zadania).

nie mogę tego stosować dla par, gdyż zakres może być tak naprawdę od 1 dnia (wtedy dzień jest osobno, tak jak w podanym przypadku) do tak naprawde nieskończenie długiego zakresu (z tym, że ważne, żeby wszystkie daty pośrednie istniały). Może pokażę na przykładzie większej liczby danych

dates = ["28-10-2010", "29-10-2010", "1-11-2010","2-11-2010", "3-11-2010", "5-11-2010", "7-11-2010","8-11-2010"] @output = {:bar => [], :not_bar => []} dates.each do |date| if Foo.bar?(date) # (...) end end @output.inspect # => { :bar => ["28-10-2010 - 3-11-2010", "5-11-2010", "7-11-2010 - 8-11-2010"], :not_bar => [] }
oczywiście zakładając, że wszystkie daty zwrócą bar? jako true. (jak nie - to dzieje się to samo, tylko że trafia do :not_bar)
wday bierze się stąd, że sprawdzam, czy następny dzień w tablicy jest nastepnym dniem roboczym (dla piątku następnym pracującym jest poniedziałek) ) aczkolwiek nie jestem pewien czy zabrałem sie za to poprawnie…

Nie jestem pewien czy to jest do końca ruby-way, ale powinno działać.

Zakładam, że masz już posortowane daty

[code=ruby] def next_cw_day(day)
cwdays = [1, 2, 3, 4, 5]
day = day.to_date

while !cwdays.include?(day.cwday) do
  day = day.next
end

return day.strftime("%e-%m-%Y").strip

end[/code]

[code=ruby] def intervals(dates)
intervals = []

dates.each_with_index do |date, i|
  @first_date = date if @first_date.nil?
  @last_date = date if @last_date.nil?

  next_day = date.to_date.next.strftime("%e-%m-%Y").strip
  date_next = dates[i+1] unless dates[i+1].nil?

  if (date_next == next_day)
    @last_date = next_day
  else if (date_next == next_cw_day(next_day))
      @last_date = date_next
  else
      intervals += @first_date == @last_date ? @first_date.to_a : (@first_date + " - " + @last_date).to_a
      @first_date = @last_date = nil
    end
  end
end

return intervals

end[/code]

[code=ruby]dates = [“28-10-2010”, “29-10-2010”, “1-11-2010”,“2-11-2010”, “3-11-2010”, “5-11-2010”, “7-11-2010”, “8-11-2010”]

intervals(dates)

=> [“28-10-2010 - 3-11-2010”, “5-11-2010”, “7-11-2010 - 8-11-2010”][/code]

działa zgodnie z oczekiwaniami. postaram się poprawić kod, i przedstawić tutaj moją wersję… a potem zakład patologii kodu (mam nadzieję) że poprawi ten kod :wink: