Search code examples
arraysrubyobjectattributesunique

Return Array of Objects/Hashes sorted by attributes


I have an array of objects, in this example represented as hashes:

[
 { "mid" => 123, "updated" => "2015-05-05 05:05:05"}
 { "mid" => 456, "updated" => "2015-05-05 05:06:05"}
 { "mid" => 789, "updated" => "2015-05-05 05:05:05"}
 { "mid" => 123, "updated" => "2015-05-05 05:05:07"}
 { "mid" => 456, "updated" => "2015-05-05 05:05:05"}
]

And I need to get back only elements with the unique mid, in a process of selecting unique objects, timestamp needs to be taken to consideration, where higher datetime is the one to return. So my examples outcome would be:

[
 { "mid" => 456, "updated" => "2015-05-05 05:06:05"}
 { "mid" => 789, "updated" => "2015-05-05 05:05:05"}
 { "mid" => 123, "updated" => "2015-05-05 05:05:07"}
]

I tried couple of different approaches, but I have a problem with my logic, I always get 20 objects back instead of 3. Here is my code:

res = []
queue.length.times do
    a = queue.pop
    queue.each do |job|
        if a.mid == job.mid
            if DateTime.parse(a.updated) >= DateTime.parse(a.updated)
                res << a
            end
        else
            res << a
        end
    end
    queue << a
end

Any idea?


Solution

  • Assuming you have your input in arr:

    arr.group_by do |h| 
      h['mid']                   # group same mids
    end.values.map do |all|
      all.max_by do |h|
        Date.parse h['updated']  # pick latest by date
      end
    end
    
    #⇒ [
    #    {"mid"=>123, "updated"=>"2015-05-05 05:05:07"},
    #    {"mid"=>456, "updated"=>"2015-05-05 05:06:05"},
    #    {"mid"=>789, "updated"=>"2015-05-05 05:05:05"}
    # ]
    

    Please avoid writing phpish code using ruby syntax.

    UPD Credits to Cary Swoveland, sort_by+last reduced to max_by.