首页 > 解决方案 > Ruby Array #count 如何处理多个块参数

问题描述

当我执行以下操作时:

[[1,1], [2,2], [3,4]].count {|a,b| a != b} # => 1

块参数ab分别分配给每个内部数组的第一个和第二个值。我不明白这是如何实现的。

文档中给出的唯一示例 for Array#countand Enumerable#countwith a block 使用单个块参数:

ary.count {|x| x % 2 == 0} # => 3

标签: ruby

解决方案


就像作业一样,有一个(不那么)秘密的捷径。如果右边是一个数组,而左边有多个变量,则数组是 splatted,所以下面两行是相同的:

a, b, c = [1, 2, 3]
a, b, c = *[1, 2, 3]

虽然不是一回事,但当产生的值是一个数组并且有多个参数时,块具有相同的含义。因此,当您执行以下操作时,这两个块的作用相同yield [1, 2, 3]

do |a, b, c|
  ...
end

do |(a, b, c)|
  ...
end

因此,在您的情况下,该值被解构,就好像您这样写:

[[1,1], [2,2], [3,4]].count {|(a,b)| a != b} # => 1

如果您有与数组一起传递的另一个值,则必须显式指定结构,因为数组的解构不会按照我们想要的方式自动进行:

[[1,1], [2,2], [3,4]].each.with_index.count {|e,i| i + 1 == e[1] }
# automatic deconstruction of [[1,1],0]:
# e=[1,1]; i=0

[[1,1], [2,2], [3,4]].each.with_index.count {|(a,b),i| i + 1 == b }
# automatic deconstruction of [[1,1],0], explicit deconstruction of [1,1]:
# a=1; b=1; i=0

[[1,1], [2,2], [3,4]].each.with_index.count {|a,b,i| i + 1 == b }
# automatic deconstruction of [[1,1],0]
# a=[1,1]; b=0; i=nil
# NOT what we want

推荐阅读