如何通过对象中的值将对象分组到嵌套对象中?

时间:2013-10-01 16:20:50

标签: ruby-on-rails ruby enumeration

这是我在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 :(得分:2)

保持订单使用Enumerable的{​​{3}}方法:

@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"}
#=> ]

<强>更新

您可以动态更改输出格式:)

对于您的上一个变体,请尝试以下方法:

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

答案 1 :(得分: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"}]]