2010-06-21 111 views
0

嘿,夥計們,我有一個問題。我想轉換數組。 [[1, [-1, 1]], [1, [20, 8]], [1, [30, 4]], [1, [40, 2]], [1, [41, 6]], [1, [70, 243]]]進入這種風格[1,[[-1,1],[20,8],[30,4]...]或哈希[1 => ...] 我該怎麼辦這個伎倆?謝謝 !紅寶石陣列的問題!

回答

6

快譯通方法:

array = [your array] 
dict = {} 
array.each{ |a| (dict[a[0]] ||= []) << a[1] } 

爲了清晰Chuck的建議是要把這個:

array = [your array] 
dict = Hash.new {|h,k| h[k] = []} 
array.each{ |a| dict[a[0]] << a[1] } 

然後,您可以通過做從中得到的風格,你想數組:

new_arr = dict.select{|k,v| [k, v]} 

這會給你:

[[1, [[-1, 1], [20, 8], [30, 4], [40, 2], [41, 6], [70, 243]]]] 

注意額外的數組,因爲如果你的數組是2開始的,你會在結尾有另一個數組。所以new_arr[0]會給你你最初尋找的陣列。

+3

你也可以很容易地派生出這樣的數組。創建散列,然後執行'hash.map {| key,values | [key,values]}'。另外,通過將哈希創建爲'Hash.new {[]}',您可以大大簡化您的'each' - 然後在每次迭代中不需要對'|| = []'進行操作,因爲不存在的鍵將返回一個空陣列。 – Chuck 2010-06-21 04:39:19

+0

'Hash.new {[]}'只適用於像'+ ='這樣的賦值操作符,但是'''它不會。我相應地編輯了答案。 – 2010-06-22 00:57:23

0

你可以這樣做:

array = [[1, [-1, 1]], [1, [20, 8]], [1, [30, 4]], 
     [1, [40, 2]], [1, [41, 6]], [1, [70, 243]]] 

# map into hashes that can be merged together 
hashes = array.map do |key,value| 
    { key => [value] } 
end 

# fold all hashes into one hash by merging the values by key 
merged_hash = hashes.inject({}) do |accu,value| 
    accu.merge!(value) {|_,o,n| o|n } 
end 

這可以寫成一個不是那麼容易的一行:

array.map{|k,v|{k=>[v]}}.inject({}){|a,v|a.merge!(v){|_,o,n|o|n}} 
#==> {1=>[[-1, 1], [20, 8], [30, 4], [40, 2], [41, 6], [70, 243]]} 
+0

這似乎比馬特的解決方案更復雜,沒有任何好處。你爲什麼喜歡這種做法? – Chuck 2010-06-21 05:30:15

+0

@Chuck它通過使用'inject'來解決問題,而不會污染局部變量名稱空間。我更喜歡|| = []的'merge'方法。當然這是一個品味問題。但我認爲Matt的解決方案也可以使用'inject'重寫,從而防止用臨時變量污染命名空間。 – hurikhan77 2010-06-21 07:45:46

2

如果你想把它當作一個Hash,它只是

h = Hash[ary.group_by(&:first).map {|k, v| [k, v.map(&:last)] }] 

如果你想要它作爲Array,你只需將Hash轉換爲一個Array

a = *h 
+0

+1爲一個非常優雅的解決方案,但我想提一下,group_by可能不適用於較舊的ruby API。 – hurikhan77 2010-06-21 11:58:40

+0

我相信'.group_by'是ruby 1.9,儘管可能有rails選項。 – 2010-06-21 13:49:13

+0

該代碼在Ruby 1.8.7及更新版本中未修改運行。要在Ruby 1.8.6中使用它,你必須要求''Enumerable#group_by'和'Symbol#to_proc'的backports。 – Chuck 2010-06-22 00:04:33