2013-06-06 63 views
2

哈希比方說,我有這兩個數組:對元素融入在Ruby中

a = [1, 2, 3, 4, 5] 
b = [6, 7, 8, 9, 10] 

我想要得到的是一個Hash如下:

c = { 1 => [1, 6], 2 => [2, 7], 3 => [3, 8], 4 => [4, 9], 5 => [5, 10] } 

的唯一途徑到目前爲止我遇到如下:

# Initialize the resulting Hash and fill in the keys. 
c = {} 
(a.length).times { |i| c[i + 1] = [] } 

# Fill values 
c.each_with_index do |(key), idx| 
    c[key] = [a[idx], b[idx]] 
end 

Ruby是否有更好或更好的方法來做到這一點?

在此先感謝。

回答

10

功能的方法:

Hash[a.zip(b).map.with_index(1) { |pair, idx| [idx, pair] }] 
#=> {1=>[1, 6], 2=>[2, 7], 3=>[3, 8], 4=>[4, 9], 5=>[5, 10]} 

只是爲了好玩,如果你想建立自己的抽象:以前的片段是比它應該是因爲with_index更詳細的,首先它只能在普查員(不是可枚舉的),其次它將該值作爲第二個元素(它將作爲第一個元素更有用,這是大多數其他語言所做的)。我們能做什麼?添加我們自己的Enumerable#indexed方法,反過來工作。在這一點上我們就被迫還加Enumerable#to_h,所以最後我們就可以寫這種純OOP,左到右,聲明代碼:

a.zip(b).indexed(1).to_h 
+0

'with_index(1,&:reverse)'能工作嗎? – sawa

+0

@sawa:不,但我不知道爲什麼。 – tokland

+2

我明白了。我錯了。我找出原因。當使用'to_proc'並且該塊帶有多個塊參數時,第一個變爲接收者,其餘爲參數。 – sawa

0

Ruby對此有更好或更好的方法嗎?

當然,它確實!

a = [1, 2, 3, 4, 5] 
b = [6, 7, 8, 9, 10] 

c = a.zip(b).each.with_index.with_object({}) do |(arr, idx), memo| 
    memo[idx + 1] = arr 
end 

C# => {1=>[1, 6], 2=>[2, 7], 3=>[3, 8], 4=>[4, 9], 5=>[5, 10]} 
8
c = Hash[(1..a.size).zip(a.zip(b))] 

它利用了Hash's key-value pair initializer

+0

+1雙'拉鍊'是少說聲明,但我也喜歡它。恕我直言,問題在於Ruby中的索引是錯誤的,它們作爲第一個元素更有用,而不是最後一個。然後我們可以寫'Hash [a.zip(b).indexed(1)]'或類似的東西。 – tokland

+0

+1給你,我的靈感來自你的答案:D –

+0

或者在你的特殊情況下,其中a包含密鑰,甚至更短 '哈希[a.zip(a.zip(b))]'' – ovhaag

0

你已經有了很多很好的答案。爲了多樣性我會再增加兩個。

Hash[(0...a.size).map{ |i| [i+1, [a[i], b[i]]] } ] 

(0...a.size).each_with_object({}) { |i, h| h[i+1] = [a[i], b[i]] } 

我要說的版本更容易閱讀和理解。 :)但是,這是一個品味問題。

UPDATE:

我caaaaaannot停止。 :-)這裏還有一個:

a.zip(b).each_with_object({}) { |p, h| h[h.size+1] = p }