我有一组对象@users
,每个对象都有id
属性。
@users = [#<User id:1>, #<User id:2>]
我还有一个ids
的有序数组。
ids = [2,1]
¿是否有一种使用该ID列表对集合进行排序的神奇方法?如果可能的话,不要再次调用数据库。
谢谢!!!
答案 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