奇怪的乘数运算符行为在两个数组中进行哈希组合

我一直在寻找一种方法将两个数组转换为单个哈希。 我发现了这样的事情:

a1 = [1,2,3] a2 = [?A, ?B, ?C] Hash[*a1.zip(a2).flatten] 

我认为这种语法Hash[a1.zip a2] ,因为Hash[a1.zip a2]会做同样的事情。 但更重要的是,我不明白需要*运算符。

我知道它将对象转换为数组或类似的东西(但显然不是以[]方式)。

当我执行:

 a = a1.zip(a2).flatten => [1, "A", 2, "B", 3, "C"] a = *a1.zip(a).flatten => [1, "A", 2, "B", 3, "C"] 

什么都没发生,而且对于我所知道的*运算符,这似乎是正常的行为。

那么,为什么呢

 Hash[*a1.zip(a2).flatten] => {1=>"A", 2=>"B", 3=>"C"} Hash[a1.zip(a).flatten] => {} 

如果参数看起来相同,则返回不同的值?

我想我一定错过了关于*运算符的东西。

谢谢。

*运算符与数组一起使用时,它被称为splat运算符

可以将其视为删除数组周围第一级括号的运算符 。 这非常有用,因为您可以将数组转换为参数列表:

 def stuff(x, y, z) end a = [1, 2, 3] stuff(*a) # x,y,z gets assigned 1,2,3 

同样适用于Hash[]Hash上的[]运算符接受为参数:

  1. 键值对的参数列表:
    Hash["a", 1, "b", 2] #=> { "a" => 1, "b" => 2 }
  2. 表示键值的数组或数组对:
    Hash[ [["a", 1], ["b", 2]] ] #=> { "a" => 1, "b" => 2 }

Hash[]不接受普通的平面数组作为参数:

 Hash[ ["a", 1, "b", 2] ] #=> {} 

因此,考虑到这一点,加上我们对splat运算符的理解,您现在可以看到正在发生的事情:

 paired_array = a1.zip(a2) => [[1, "A"], [2, "B"], [3, "C"]] plain_array = a1.zip(a2).flatten => [1, "A", 2, "B", 3, "C"] # Per rule 2 above we know this works Hash[paired_array] => {1=>"A", 2=>"B", 3=>"C"} # This won't work Hash[plain_array] => {} # But if we turn the plain_array into an argument list, # then we know per rule 1 above that this will work Hash[*plain_array] => {1=>"A", 2=>"B", 3=>"C"} 

现在你可能想知道当你做什么时嘿嘿发生了什么:

 a = *plain_array => [1, "A", 2, "B", 3, "C"] 

由于我们知道splat运算符有效地剥离括号,我们得到:

 a = 1, "A", 2, "B", 3, "C" 

…有趣的是有效的Ruby代码,只是再次创建一个数组。

您可以在splat操作符的rubyspec测试用例中阅读有关splat操作符的更多有趣内容。

我认为你的例子中有一个错误,它应该是这样的:

 Hash[a1.zip(a2).flatten] #=> {} Hash[*a1.zip(a2).flatten] #=> {1=>"A", 2=>"B", 3=>"C"} 

分配模式下的splat运算符将数组转换为多个参数:

 duck, cow, pig = *["quack","mooh","oing"] #=> ["quack","mooh","oing"] 

实际上它是完全相同的

 duck, cow, pig = ["quack","mooh","oing"] #=> ["quack","mooh","oing"] 

但是从文档中你可以看到Hash […]接收到多个参数,因此splat运算符有助于分配这些多个参数中的每一个。

这不是那么神秘:

 a1 = [1,2,3] a2 = [?A, ?B, ?C] p Hash[*a1.zip(a2).flatten] #{1=>"A", 2=>"B", 3=>"C"} 

*将数组转换为纯粹的参数列表。

但为什么不使用这种语法?

 p Hash[a1.zip(a2)]# {1=>"A", 2=>"B", 3=>"C"} 

嗯,这是Ruby 1.9.2以来的新function。 你的例子可能更老。