如何交错多个 ActiveRecord 关联查询?

How to interleave multiple ActiveRecord association queries?

我有五个类别,每个类别大约有五个帖子。例如

=> category_a.posts
=> #<Post id:01>, #<Post id:02>, #<Post id:03> etc

=> category_b.posts
=> #<Post id:10>, #<Post id:11>, #<Post id:12> etc

=> category_c.posts
=> #<Post id:20>, #<Post id:21>, #<Post id:22> etc

我想要一个 children 的集合,它们交错排列(尽可能均匀),即

#<Post id:01>, #<Post id:10>, #<Post id:20>, #<Post id:02>, #<Post id:11> etc

我怎样才能做到这一点?

只有五个查询和大约 15 个模型,所以在内存中完成就可以了:

 posts =
   [category_a, category_b, category_c, category_d, category_e].
   map(&:posts)
   sort_by(&:length)
 posts.first.zip(*posts[1..-1]).flatten.compact

将最长的数组放在第一位可以防止 zip 从其参数中的数组中删除比调用它的数组长的元素。 compact 删除由 zip 创建的任何 nil 如果其参数中的数组比调用它的数组长。

Dave Schweisguth 的回答还不错,可能会让您知道解决问题所需的知识。但是,该解决方案不允许您选择项目交错的顺序。希望这是一个更通用的解决方案:

def full_zip(*args)
  max_len = args.map(&:length).max
  ([nil] * max_len).zip(*args).flatten.compact
end

然后这将像 full_zip(category_a.posts, category_b.posts, category_c.posts)full_zip(*[cat_a, cat_z].map(&:posts)) 一样使用。按照您希望的顺序使用类别。

编辑:这个问题的一个问题是如果原始列表中有 nils 你想保留。