2013-10-01 3 views
1

Вот объект, с которым я работаю в Ruby. Это куча событий, отсортированных по дате, но я хочу, чтобы объект был на один уровень глубже, если в объекте есть два или более одного объекта event_type.Как объединить объекты в вложенные объекты по значению в объекте?

@events = [ 
    { :id => 1, :event_type => "B", :created_at => "2013-09-30 14:44:24 UTC"}, 
    { :id => 2, :event_type => "A", :created_at => "2013-09-29 14:44:24 UTC"}, 
    { :id => 3, :event_type => "A", :created_at => "2013-09-28 14:44:24 UTC"}, 
    { :id => 4, :event_type => "C", :created_at => "2013-09-27 14:44:24 UTC"}, 
    { :id => 5, :event_type => "C", :created_at => "2013-09-26 14:44:24 UTC"}, 
    { :id => 6, :event_type => "A", :created_at => "2013-09-25 14:44:24 UTC"} 
] 

Я ищу, чтобы превратить его в это:

@events = [ 
    { :id => 1, :event_type => "B", :created_at => "2013-09-30 14:44:24 UTC"}, 
    { :grouped_events => [ 
      { :id => 2, :event_type => "A", :created_at => "2013-09-29 14:44:24 UTC"}, 
       { :id => 3, :event_type => "A", :created_at => "2013-09-28 14:44:24 UTC"} 
      ] 
     }, 
    { :grouped_events => [ 
      { :id => 4, :event_type => "C", :created_at => "2013-09-27 14:44:24 UTC"}, 
      { :id => 5, :event_type => "C", :created_at => "2013-09-26 14:44:24 UTC"} 
      ] 
     }, 
    { :id => 6, :event_type => "A", :created_at => "2013-09-25 14:44:24 UTC"} 
] 

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

+0

You не может иметь две клавиши с одинаковыми name (': event') – Pol0nium

+0

Хорошая точка, исправлена. – scottdevries

+0

@Scott, я понятия не имею, если вы считаете это предпочтительным (и вы, вероятно, подумали об этом), но вместо этого вы можете использовать @events = [[{: id => 1, .. UTC "}], [{ : id => 2, .. UTC "},: id => 3, .. UTC"}], [{: id => 4, .. UTC "}, {: id => 5, .. UTC" }], [{: id => ..UTC "}]' –

ответ

2

Чтобы использовать порядок chunk метод Enumerable:

@events = [ 
{ :id => 1, :event_type => "B", :created_at => "2013-09-30 14:44:24 UTC"}, 
{ :id => 1, :event_type => "A", :created_at => "2013-09-29 14:44:24 UTC"}, 
{ :id => 1, :event_type => "A", :created_at => "2013-09-28 14:44:24 UTC"}, 
{ :id => 1, :event_type => "C", :created_at => "2013-09-27 14:44:24 UTC"}, 
{ :id => 1, :event_type => "C", :created_at => "2013-09-26 14:44:24 UTC"}, 
{ :id => 1, :event_type => "A", :created_at => "2013-09-25 14:44:24 UTC"} 
] 

p @events.chunk{|el| el[:event_type]}.map{|gr| gr[1]} 

Выход:

#=> [[{:id=>1, :event_type=>"B", :created_at=>"2013-09-30 14:44:24 UTC"}], 
#=> [{:id=>1, :event_type=>"A", :created_at=>"2013-09-29 14:44:24 UTC"}, 
#=> {:id=>1, :event_type=>"A", :created_at=>"2013-09-28 14:44:24 UTC"}], 
#=> [{:id=>1, :event_type=>"C", :created_at=>"2013-09-27 14:44:24 UTC"}, 
#=> {:id=>1, :event_type=>"C", :created_at=>"2013-09-26 14:44:24 UTC"}], 
#=> [{:id=>1, :event_type=>"A", :created_at=>"2013-09-25 14:44:24 UTC"}]] 

Или, если вы хотите иметь массивы только тогда, когда есть 2 или более элементов попробуйте следующее:

p @events 
    .chunk{|el| el[:event_type]} 
    .flat_map{|gr| gr[1].length == 1 ? gr[1] : [gr[1]]} 

Выход будет

#=> [ 
#=> {:id=>1, :event_type=>"B", :created_at=>"2013-09-30 14:44:24 UTC"}, 
#=> [{:id=>1, :event_type=>"A", :created_at=>"2013-09-29 14:44:24 UTC"}, 
#=> {:id=>1, :event_type=>"A", :created_at=>"2013-09-28 14:44:24 UTC"}], 
#=> [{:id=>1, :event_type=>"C", :created_at=>"2013-09-27 14:44:24 UTC"}, 
#=> {:id=>1, :event_type=>"C", :created_at=>"2013-09-26 14:44:24 UTC"}], 
#=> {:id=>1, :event_type=>"A", :created_at=>"2013-09-25 14:44:24 UTC"} 
#=> ] 

Update

Вы можете изменить формат вывода на лету :)

Для последнего варианта попробуйте это:

p @events 
    .chunk{|el| el[:event_type]} 
    .flat_map{|gr| 
    gr[1].length == 1 ? gr[1] : {:grouped_events => gr[1]} 
    } 
+0

+1 .... хороший – tihom

+0

Да, извините за изменение вывода на вас ... понял, что мне нужно что-то маленькое, немного другое. Любите свой подход здесь! – scottdevries

+0

Всё нормально. Кстати, ваши данные ошибочны. Не может быть '...: event_type =" B "...', это должно быть '...: event_type =>" B "...'. –

0

насчет

p @events.group_by{|item| item[:event_type]}.values #=> 

# [[{:id=>1, :event_type=>"B", :created_at=>"2013-09-30 14:44:24 UTC"}], 
# [{:id=>1, :event_type=>"A", :created_at=>"2013-09-29 14:44:24 UTC"}, 
# {:id=>1, :event_type=>"A", :created_at=>"2013-09-28 14:44:24 UTC"}, 
# {:id=>1, :event_type=>"A", :created_at=>"2013-09-25 14:44:24 UTC"}], 
# [{:id=>1, :event_type=>"C", :created_at=>"2013-09-27 14:44:24 UTC"}, 
# {:id=>1, :event_type=>"C", :created_at=>"2013-09-26 14:44:24 UTC"}]] 
+0

Это группирует события по типу события, не принимая во внимание порядок событий. Мне нужно, чтобы события отсортировались по дате и событию. – scottdevries

+0

Ой, пропустил эту часть. То же самое, но метод, который вы ищете, это кусок, посмотрите на ответ Евгения Анфилофеева. – hirolau

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