A more functional programming approach:
User = Struct.new(:user_id, :num_hot_dogs_eaten, :date_last_pigged_out)
ONE_DAY = 60 * 60 * 24
class Object
def returning(object)
yield object
object
end
end
users = [
User.new(1, 3, Time.now),
User.new(1, 2, Time.now + ONE_DAY),
User.new(1, 1, Time.now - ONE_DAY),
User.new(2, 2, Time.now - ONE_DAY),
User.new(2, 3, Time.now),
User.new(3, 5, Time.now - ONE_DAY),
]
users.inject(Hash.new { |hash, key| hash[key] = Hash.new { |hash, key| hash[key] = [] } }) do |collection, user|
returning(collection) do
collection[user.user_id][:num_hot_dogs_eaten] << user.num_hot_dogs_eaten
collection[user.user_id][:date_last_pigged_out] << user.date_last_pigged_out
end
end.map do |user_id, stats|
User.new(user_id, stats[:num_hot_dogs_eaten].inject(&:+), stats[:date_last_pigged_out].max)
end.sort_by { |user| [user.num_hot_dogs_eaten, user.date_last_pigged_out] }.reverse
The actual implementation is (assuming you have returning
defined):
users.inject(Hash.new { |hash, key| hash[key] = Hash.new { |hash, key| hash[key] = [] } }) do |collection, user|
returning(collection) do
collection[user.user_id][:num_hot_dogs_eaten] << user.num_hot_dogs_eaten
collection[user.user_id][:date_last_pigged_out] << user.date_last_pigged_out
end
end.map do |user_id, stats|
User.new(user_id, stats[:num_hot_dogs_eaten].inject(&:+), stats[:date_last_pigged_out].max)
end.sort_by { |user| [user.num_hot_dogs_eaten, user.date_last_pigged_out] }.reverse