【问题标题】:Iterating over an array of arrays遍历数组数组
【发布时间】:2014-09-09 18:49:50
【问题描述】:
def compute(ary)
  return nil unless ary
  ary.map { |a, b| !b.nil? ? a + b : a }
end

compute([1,2],[3,4])

有人可以向我解释一下 compute 如何添加内部数组的值吗?

在我看来,在该数组数组上调用 map 似乎会将两个数组相加,而不是每个数组的内部元素。

【问题讨论】:

  • 我试过这个并得到“在`compute'中:错误数量的参数(2 for 1)(ArgumentError)”
  • 我从 RubyMonk 逐行复制了这段代码,我注意到他使用的代码有点时髦。我从来没有在 IRB 中尝试过这个,所以谢谢你的提醒。

标签: ruby arrays map enumerable


【解决方案1】:

我想这是我自己想出来的。

map 选择数组数组的第一个数组并将其通过管道传输到块中。变量ab 因此引用第一个数组的内部元素,而不是数组数组中的第一个数组和第二个数组。

【讨论】:

  • 不,map 不选择任何内容。正如 Some Guy 评论的那样,您的代码会引发错误,并且一开始就不会运行。
【解决方案2】:

map 基本上是遍历对象的元素:

foo = [
  ['a', 'b'],
  ['c', 'd']
]

foo.map{ |ary| puts ary.join(',') }
# >> a,b
# >> c,d

在本例中,它传递每个子数组,分配给ary

换个角度看:

foo.map{ |ary| puts "ary is a #{ary.class}" }
# >> ary is a Array
# >> ary is a Array

因为 Ruby 允许我们一次分配多个值,所以可以这样写:

foo.map{ |item1, item2| puts "item1: #{ item1 }, item2: #{ item2 }" }
# >> item1: a, item2: b
# >> item1: c, item2: d

如果map 正在对哈希数组进行迭代,则每次迭代都会产生块的子哈希:

foo = [
  {'a' => 1},
  {'b' => 2}
]

foo.map{ |elem| puts "elem is a #{ elem.class }" }
# >> elem is a Hash
# >> elem is a Hash

如果map 正在对哈希进行迭代,则每次迭代都会产生块的键/值对:

foo = {
  'a' => 1,
  'b' => 2
}

foo.map{ |k, v| puts "k: #{k}, v: #{v}" }
# >> k: a, v: 1
# >> k: b, v: 2

但是,如果你只给块一个参数,Ruby 会将键和值都分配给变量,所以你会看到它是一个数组:

foo.map{ |ary| puts "ary is a #{ary.class}" }
# >> ary is a Array
# >> ary is a Array

因此,当您遍历容器以及 Ruby 将值传递到 map 的块中时,您必须了解正在发生的多种事情。

除此之外,重要的是要记住map 将为传入的每个内容返回一个或多个值。map,又名collect,用于转换值。它不应该被用作each 的替代品,它只会迭代。在上面的所有示例中,我并没有真正展示 map 的正确使用,因为我试图展示传入的元素会发生什么。通常我们会这样做:

foo = [['a', 'b'], ['c', 'd']]
foo.map{ |ary| ary.join(',') }
# => ["a,b", "c,d"]

或者:

bar = [[1,2], [3,4]]
bar.collect{ |i, j| i * j }
# => [2, 12]

还有map! 改变被迭代的对象,而不是返回值。我建议避免使用map!,直到您清楚地知道它为什么对您有用,因为除非他们了解变量的传递方式以及数组和哈希的工作原理,否则它似乎会让人们感到困惑。

最好的办法是在 IRB 中使用map。您将能够更轻松地看到正在发生的事情。

【讨论】:

  • 当您在管道中使用两个变量而不是一个变量时,我只是对块背后的机制感到困惑。您使用一个变量,并且 ruby​​ 知道您指的是数组中的每个数组。您使用两个,Ruby 知道您指的是数组中每个单独数组中的每个单独元素。不过谢谢。你的例子很有帮助。
  • @BoG.:块和 Procs 的参数绑定使用与方法和 lambda 的参数绑定不同的语义。块和Procs 的参数绑定比方法/lambda 参数语义更接近赋值语义。 (事实上​​,直到 Ruby 1.8,blocks/Procs 实际上使用 赋值语义。)请参阅stackoverflow.com/a/19841196/2988stackoverflow.com/a/2270433/2988stackoverflow.com/a/16073076/2988 获取一些示例。想想Hash#eachHash#map 和朋友们,如果不是这种情况,他们会多么尴尬。
猜你喜欢
  • 2016-01-31
相关资源
最近更新 更多