2012-06-27 25 views
2

我正在尋找一種將兩個數組轉換爲單個哈希的方法。我發現這樣的事情:兩個數組哈希組合中的奇怪multiplicator操作符行爲

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

*運算符與像這樣的數組一起使用時,它被稱爲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] ] #=> {} 

那麼一點,再加上我們的理解是什麼圖示符不,你現在可以看到正在發生的事情:

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"] 

既然我們知道了圖示運營商有效地去掉括號,我們可以得到這樣的:

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

.. 。有趣的是有效的Ruby代碼,並且只是再次創建一個數組。

您可以在rubyspec test case for the splat operator中閱讀更多關於摔跤運算符的有趣內容。

+0

非常感謝,明白了:) –

2

我覺得有一個在你的榜樣錯誤,它應該是這樣的:

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

在分配模式的圖示運算符將數組多個參數:

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

其實是相同的到

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

但是從documentation你可以看到哈希[。 ..]接收多個參數,所以splat操作符有助於分配這些多個參數中的每一個。

+0

是的,我修好了,謝謝! –

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開始的新的。你的例子可能比較老。

+0

哦,那是一個古老的例子,好吧!謝謝 :) –