2

给定

a = nil # or [1,2]
b = [1,2] # or nil

您能否在不分配中间体或创建大量样板代码的情况下迭代连接a和连接?b

# 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
4

3 回答 3

2

好吧,如果您愿意创建一个容器(即使包含的元素很大,它也应该很便宜),您可以:

[a,b].compact.each do |e|
  e.each do
    # stuff
  end
end

您确实必须创建一个容器数组,但由于您不必复制子数组的内容(而只是处理两个数组指针),因此它应该非常快并且在 GC 上并不可怕。

另一种解决方案可能只是创建一个方法:

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
于 2012-09-14T04:01:59.577 回答
2

如果您使用的是 1.9,我会使用多个 splats 的功能:

a = nil
b = [1, 2]
[*a, *b]
#=> [1, 2]

a = [3, 4]
b = nil
[*a, *b]
#=> [3, 4]

所以[*a, *b].each {}看起来就像你想要的。

于 2012-09-14T06:12:05.290 回答
1

通过将 lambda 作为块本身传递,可以使您拥有的内容更加简洁且不那么难看:

l = lambda { |thing| do_my_thing }
a.each(&l) if a
b.each(&l) if b
于 2012-09-14T04:25:49.430 回答