Сортировка массива объектов по упорядоченному списку идентификаторов - PullRequest
9 голосов
/ 17 октября 2011

У меня есть коллекция объектов @users, каждый из которых имеет свой атрибут id.

@users = [#<User id:1>, #<User id:2>]

У меня также есть заказанный массив ids.

ids = [2,1]

¿Есть ли волшебный способ сортировки коллекции с использованием этого списка идентификаторов? Без повторного вызова базы данных, если это возможно.

Спасибо !!!

Ответы [ 4 ]

20 голосов
/ 17 октября 2011

На самом деле вам не нужно сортировать, строить промежуточный индексированный хеш, это O (n):

users_by_id = Hash[@users.map { |u| [u.id, u] }]
users_by_id.values_at(*ids)

Если вы все еще хотите попробовать подход сортировки, преобразование Шварца будет достаточно:

@users.sort_by { |u| ids.index(u.id) }

Однако использование index в цикле означает красный флаг: O (n ^ 2) время.Мы можем создать промежуточный хеш, чтобы вернуться к O (n * log n):

indexes = Hash[ids.each_with_index.to_a]
@users.sort_by { |u| indexes[u.id] }
11 голосов
/ 17 октября 2011

Попробуй это. Сначала создайте обратное отображение из id -> user.

ids_users = {}

@users.each {|user| ids_users[user.id] = user}

Затем используйте порядок идентификаторов

ids.collect{ |id| ids_users[id] }
1 голос
/ 17 октября 2011

Вам определенно не нужно идти в БД, поскольку у вас уже есть объекты User, хотя, поскольку пользователи находятся в массиве, вам, вероятно, потребуется создать временную картуid => User, чтобы получить конечный результат.

0 голосов
/ 17 октября 2011

Если вы можете получить доступ к идентификатору каждого пользователя, вызвав user.id, вы можете отсортировать массив следующим образом:

@users.sort!{|a,b| a.id <=> b.id }

Если у вас есть только идентификаторы в отдельном массиве от объектов, вы можете сделать следующее: Сожмите два массива вместе, отсортируйте полученный массив по идентификаторам, затем соберите отсортированных пользователей из результата.

users_ids = @users.zip(ids) # creates an array of smaller arrays each holding [user, id]
users_ids.sort!{|a,b| a[1] <=> b[1]} # sorts on the id in each sub-array
sorted_users = users_ids.collect{|item| item[0]} #grabs the users, leaving the ids behind

Взгляните на это: http://ariejan.net/2007/01/28/ruby-sort-an-array-of-objects-by-an-attribute

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...