如何交错多个 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 你想保留。
我有五个类别,每个类别大约有五个帖子。例如
=> 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 你想保留。