Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 如何有效地迭代合并两个可枚举项?_Ruby_Arrays_Performance - Fatal编程技术网

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]