如何根据id数组重新排序activerecord数组

时间:2013-05-09 13:24:22

标签: ruby arrays ruby-on-rails-3 activerecord

我有一个现有的activerecord数组,得到以下结果:

@posts = Post.where(["created_at > ?", n_days.days.ago])

我想基于需要从多个列实时计算的值来订购此数组:

posts_array = posts.map { |p| [p.id, f(t, p.x,p.y)] }

这会给出一个类似[[1,20],[2,11],[3,14], ...]的数组,然后根据函数值对其进行排序,以提供[[1,20],[3,14],[2,11],...],然后最终得到我想要的order_array[1,3,2,...]

根据新@posts order_array重新排序原始[1,3,2,...]数组的最佳方法是什么?如果可能,我不想再次触摸数据库,因为该信息已包含在@posts数组中。

有直接的方法吗?

2 个答案:

答案 0 :(得分:4)

如果您不需要posts_array数组,则可以

@posts = Post.where(["created_at > ?", n_days.days.ago])
@posts.sort_by! { |p| f(t, p.x, p.y) }

答案 1 :(得分:1)

获取o​​rder_array

显而易见的答案是:

[[1,20],[2,11],[3,14]].sort{|a,b| b[1] <=> a[1]}.map{|x| x[0]}
 => [1, 3, 2] 

不确定某人是否能想出更聪明的东西?

在ruby 2.0上,您可以使用lazy来避免在排序后扩展数组(并获得一些性能)

[[1,20],[2,11],[3,14]].lazy.sort{|a,b| b[1] <=> a[1]}.map{|x| x[0]}

按顺序检索帖子

最简单的解决方案是

Post.find(order_array).sort{|a,b| order_array.index(a.id) <=> order_array.index(b.id)}

但简直就是

order_array.map{|x| Post.find(x)}

或者使用已加载的@post列表:

 order_array.map{|x| @post.find{|y| y.id == x)}