Продвинутая группировка в Ruby - PullRequest
0 голосов
/ 11 марта 2012

Я хочу сгруппировать события по дням.Префект:

   Available days are 1,2,3,4,5,6,7
   One event can not contain duplicates. e.g [1,1,2,3]
   Setup is Ruby 1.9.2 with Rails 3.2

Событие содержит примерно 8-10 дополнительных атрибутов (необязательно включать в пример, но следует учитывать, что эти атрибуты должны оставаться там после группировки.) Другими словами, объекты события должныне может быть изменено только сгруппировано как есть.

Рассмотрим массив с объектами:

events = [
  {
    :name => "event1",
    :days => [1,2,3,4,5]
  },
  {
    :name => "event2",
    :days => [1,4,5]
  },
  {
    :name => "event3",
    :days => [1]
  },
  {
    :name => "event4",
    :days => [2]
  },
  {
    :name => "event5",
    :days => [3]
  },
  {
    :name => "event6",
    :days => [4]
  },
  {
    :name => "event7",
    :days => [5]
  },
  {
    :name => "event8",
    :days => [1,2,3]
  },
  {
    :name => "event9",
    :days => [1,5]
  },
  {
    :name => "event10",
    :days => [1,2]
  },
  {
    :name => "event11",
    :days => [1,2,3,4,5]
  }
]

Для группировки событие должно иметь как минимум 3 дня.И эти дни должны быть в числовом порядке.

Пример (должен быть сгруппирован): [1,2,3]

Пример (долженне группироваться): [1,4,5]

События, которые не подходят для группировки, следует размещать в каждый день, который они содержат.

Пример: [1,4,5] следует поместить в 1,4 и 5.

Требуемый результат массива событий выше:

[
  {
    :heading => "1",
    :events => [
      {
        :name => "event3",
        :days => [1]
      },
      {
        :name => "event9",
        :days => [1,5]
      },
      {
        :name => "event10",
        :days => [1,2]
      },
      {
        :name => "event2",
        :days => [1,4,5]
      }
    ]
  },
  {
    :heading => "2", 
    :events => [
      {
        :name => "event4",
        :days => [2]
      },
      {
        :name => "event10",
        :days => [1,2]
      }
    ]
  },
  {
    :heading => "3",
    :events => [
      {
        :name => "event5",
        :days => [3]
      }
    ]
  },
  {
    :heading => "4",
    :events => [
      {
        :name => "event6",
        :days => [4]
      },
      {
        :name => "event2",
        :days => [1,4,5]
      }
    ]
  },
  {
    :heading => "5",
    :events => [
      {
        :name => "event7",
        :days => [5]
      },
      {
        :name => "event9",
        :days => [1,5]
      },
      {
        :name => "event2",
        :days => [1,4,5]
      }
    ]
  },
  {
    :heading => "1-3",
    :events => [
      {
        :name => "event8"
      }
    ]
  },
  {
    :heading => "1.5",
    :events => [
      {
        :name => "event1"
      },
      {
        :name => "event11"
      }
    ]
  }
]

Это очень продвинутыйРуби здесь.Может быть, слишком продвинутый для меня, все, что я пробовал, заканчивалось тем, что пропускало одну часть уравнения.Но эй, это Руби, это не должно быть так сложно?

РЕДАКТИРОВАТЬ: Обновленный пример с уточнением и исправлением ожидаемого результата

Ответы [ 2 ]

2 голосов
/ 11 марта 2012
require 'pp'
pp(events.inject(Hash.new { |h, k| h[k] = [] }) do |m, e|
  days = e[:days]
  event = { :name => e[:name] }
  if days.size >= 3 && days.last - days.first + 1 == days.size
    m["%d-%d" % [days.first, days.last]] << event
  else
    days.each { |d| m[d.to_s] << event }
  end
  m
end)
1 голос
/ 11 марта 2012

Я бы немного изменил ответ DigitalRoss.Я бы изменил

    if days.size >= 3 && days.last - days.first + 1 == days.size

на

    if days.size >= 3 && (days.first..days.last).to_a == days

Это поймает [1,1,3,4] ...

Было бы также разумно отсортироватьмассив дней перед тестированием!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...