给定有序的id列表对对象数组进行排序

时间:2011-10-17 00:59:10

标签: ruby-on-rails ruby sorting

我有一组对象@users,每个对象都有id属性。

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

我还有一个ids的有序数组。

ids = [2,1]

¿是否有一种使用该ID列表对集合进行排序的神奇方法?如果可能的话,不要再次调用数据库。

谢谢!!!

4 个答案:

答案 0 :(得分:19)

实际上你不需要排序,构建一个中间索引哈希,它是O(n):

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

如果您仍想尝试排序方法,那么Schwartzian transform就足够了:

@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] }

答案 1 :(得分:11)

试试这个。首先,建立一个来自id - &gt;的反向映射。用户。

ids_users = {}

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

然后,使用ID命令

ids.collect{ |id| ids_users[id] }

答案 2 :(得分:1)

当然不需要转到数据库,因为你已经拥有User个对象,虽然因为用户在一个数组中,你可能想要创建一个临时地图id =&gt; User获得最终结果。

答案 3 :(得分:0)

如果你可以通过调用user.id来访问每个用户的id,你可以像这样对数组进行排序:

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

如果您只将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