Ruby 如何有效地迭代合并两个可枚举项?
给定 您是否可以在不分配中间代码或创建大量锅炉板代码的情况下,迭代连接Ruby 如何有效地迭代合并两个可枚举项?,ruby,arrays,performance,Ruby,Arrays,Performance,给定 您是否可以在不分配中间代码或创建大量锅炉板代码的情况下,迭代连接a和b a = nil # or [1,2] b = [1,2] # or nil 这有点难看: # meaning do this much more efficiently ((a || []) + (b || [])).each do |thing| # more lines here puts thing end 如果您愿意创建一个容器(即使包含的元素很大,也应该便宜),您可以: l = lambda{|
a
和b
a = nil # or [1,2]
b = [1,2] # or nil
这有点难看:
# meaning do this much more efficiently
((a || []) + (b || [])).each do |thing|
# more lines here
puts thing
end
如果您愿意创建一个容器(即使包含的元素很大,也应该便宜),您可以:
l = lambda{|thing| do_my_thing }
a.each{|thing| l.call(thing)} if a
b.each{|thing| l.call(thing)} if b
您确实需要创建一个容器数组,但是由于您不必复制子数组的内容(而只需处理两个数组指针),因此它应该非常快速,在GC上也不会很糟糕
另一种解决方案可能只是创建一个方法:
[a,b].compact.each do |e|
e.each do
# stuff
end
end
通过将lambda作为块本身传递,可以使您所拥有的内容变得更加简洁,并且不那么丑陋:
def multi_each(*args,&block)
args.each do |a|
a.each(&block) if a
end
end
multi_each(nil,[1],[2,3]) do |i|
puts i
end
# 1
# 2
# 3
如果您使用的是1.9,我将使用多个splat的功能:
l = lambda { |thing| do_my_thing }
a.each(&l) if a
b.each(&l) if b
因此,
[*a,*b]。每个{}
看起来都与您想要的完全一样。实际上,多次迭代似乎很好,这可能是一个很好的选择。值得注意的是,*args被强制到一个数组中,显式块传递有一个与之相关联的性能代价(),因此第二种形式的性能可能不会比第一种更高。好的一点!我想在c扩展中这样做会有点过分,如果你必须要有最高的性能,那么你就要降到c,是的。然而,枚举器迭代已经在C中实现,使用包装器数组的原始解决方案实际上不应该带来太多开销。如果这还不够快的话,ruby inline可以让您获得所需的性能,而无需编写完整的扩展。为什么不[a,b].compact.flatte.each
而不是两个嵌套的each
调用呢?对于OP所要求的似乎已经足够了。这真的很方便,我假设它确实会导致一个额外的分配,但我尽量不让这样的考虑影响干净的代码,直到它被证明是一个瓶颈。老实说,我也喜欢它,唯一担心的是我正在开发的gem在1.8上缺乏支持,我真的很想保留它,请让1.8最终消亡吧!1.9发布已经有几年了,不会再有1.8.7版本了,1.8.7-p330是最后一个版本。如果你真的想保留1.8支持,我会选择[a,b].compact.flatte.each{}
btw。
a = nil
b = [1, 2]
[*a, *b]
#=> [1, 2]
a = [3, 4]
b = nil
[*a, *b]
#=> [3, 4]