Объединение структур с одинаковым идентификатором пользователя, а затем сортировка по атрибутам - PullRequest
0 голосов
/ 07 июля 2010

У меня есть любой массив структур. Каждая структура в массиве имеет следующие атрибуты:

  1. user_id
  2. num_hot_dogs_eaten
  3. date_last_pigged_out

Вот что я хочу сделать:

  1. Найдите структуры с совпадающими user_id и объедините их в одну структурную запись, где num_hot_dogs_eaten - это сумма всех совпадающих записей, а date_last_pigged_out - самая последняя дата, когда пользователь выдал сообщение.

  2. Сортировка массива структур по num_hot_dogs_eaten (первый порядок приоритета) и по date_last_pigged_out (второй порядок приоритета ... самый последний первый).

  3. Возвращает новый отсортированный массив структур.

Ответы [ 2 ]

1 голос
/ 07 июля 2010

Используйте это:

def f(users)
  r = []
  users.each do |u|
    new_match = false
    match = r.find {|x| x.user_id == u.user_id }
    unless match
      match = u.dup
      r << match
      new_match = true
    end
    match.num_hot_dogs_eaten += u.num_hot_dogs_eaten unless new_match
    match.date_last_pigged_out =
      [match, u].max_by(&:date_last_pigged_out).date_last_pigged_out
  end
  r.sort_by {|u| [u.num_hot_dogs_eaten, u.date_last_pigged_out] }.
    reverse
end
0 голосов
/ 07 июля 2010

Более функциональный подход к программированию:

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

Фактическая реализация (при условии, что вы определили returning):

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...