2

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

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

我认为这种语法有点奇怪,因为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]
 => {}

鉴于参数看起来相同,返回不同的值?

我想我一定错过了关于*运营商的一些东西。

谢谢。

4

3 回答 3

4

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

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

def stuff(x, y, z)
end

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

同样的事情适用于Hash[]. []运算符 onHash接受作为参数:

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

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

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 运算符的ruby​​spec 测试用例中阅读有关 splat 运算符的更多有趣内容。

于 2012-06-27T09:39:45.377 回答
2

我认为您的示例中有一个错误,应该是这样的:

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 运算符有助于分配这些多个参数中的每一个。

于 2012-06-27T09:33:26.873 回答
1

这并不神秘:

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 以来的新功能。您的示例可能较旧。

于 2012-06-27T10:04:02.697 回答