2017-05-31 55 views
-4

我有這樣一個數組。幫助我獲得理想的輸出。數組操作和計數ruby

arr = [["IT", "Testing"], ["IT", "Banking Software"], ["IT", "ERP"], 
     ["IT", "Testing"], ["IT", "IT Security"], ["IT", "ERP"], 
     ["IT", "IT Security"], ["Accounting", "Offshore"], ["IT", "Testing"], 
     ["Accounting", "ACCA"]] 

我想從arr構造如下陣列(包含單個散列):

[ 
{ 
    "IT" => [["Testing", 3], ["ERP", 2], ["IT Security", 2], ["Banking Software", 1]], 
    "Accounting" => [["Offshore", 1], ["ACCA", 1]] 
} 
] 

試圖與.MAP,.group_by,但仍然沒有成功。任何幫助讚賞。

+1

你是什麼意思「沒有成功」呢?它沒有工作嗎?它給你無效的輸出嗎? – Makoto

+0

作爲寫的,這是一個問題,「我寫的代碼」。我想幫你過去,你就完蛋了,但除非你分享的細節,我也沒有辦法。 –

回答

2

代碼和例如

[arr.each_with_object(Hash.new(0)) { |pair, h| h[pair] += 1 }. 
    each_with_object(Hash.new { |h,k| h[k]=[] }) { |((a,b),n),g| g[a] << [b,n] }] 
    #=> [{"IT"=>[["Testing", 3], ["Banking Software", 1], ["ERP", 2], ["IT Security", 2]], 
    # "Accounting"=>[["Offshore", 1], ["ACCA", 1]]}] 

爲什麼含有單個散列(而不僅僅是散列)的陣列所需的目前尚不清楚。如果散列是所有需要的,只需刪除代碼中的外括號即可。

說明

Hash.new(0)有時被稱爲計數散列。 (請參閱Hash::new。)如果h = Hash.new(0)h沒有密鑰:cat,則h[:cat]將返回默認值(此處爲零),而不更改散列。當紅寶石遇到h[:cat] += 1,它做的第一件事就是展開表達:

h[:cat] = h[:cat] + 1 

如果h有一個關鍵:cath[:cat]在平等的右側是該鍵的當前值,說8 。然後我們計算

h[:cat] = 8 + 1 #=> 9 

在另一方面,如果h沒有一個關鍵:cath[:cat]右側被設置爲默認值,所以我們必須

h[:cat] = 0 + 1 #=> 0 

因此,在第一步驟中,我們計算散列如下:

g = arr.each_with_object(Hash.new(0)) { |pair, h| h[pair] += 1 } 
    #=> {["IT", "Testing"]=>3, ["IT", "Banking Software"]=>1, ["IT", "ERP"]=>2, 
    # ["IT", "IT Security"]=>2, ["Accounting", "Offshore"]=>1, ["Accounting", "ACCA"]=>1} 

這是幾乎一樣的簡單的形式

h = {} 
arr.each do |pair| 
    h[pair] = 0 unless h.key?(pair) 
    h[pair] += 1 
end 
    #=> [["IT", "Testing"], ["IT", "Banking Software"], ["IT", "ERP"], 
    # ["IT", "Testing"], ["IT", "IT Security"], ["IT", "ERP"], 
    # ["IT", "IT Security"], ["Accounting", "Offshore"], ["IT", "Testing"], 
    # ["Accounting", "ACCA"]] 
h #=> {["IT", "Testing"]=>3, ["IT", "Banking Software"]=>1, ["IT", "ERP"]=>2, 
    # ["IT", "IT Security"]=>2, 
    # ["Accounting", "Offshore"]=>1, ["Accounting", "ACCA"]=>1} 

請注意,each返回它的接收器,所以如果此代碼段被封裝在一個方法中,我們需要結束行h

第二步(使用剛剛計算的h)實現了以下功能。

g = {} 
h.each do |k,n| 
    a, b = k 
    g[a] = [] unless g.key?(a) 
    g[a] << [b, n] 
end 
g # => {"IT"=>[["Testing", 3], ["Banking Software", 1], ["ERP", 2], ["IT Security", 2]], 
    #  "Accounting"=>[["Offshore", 1], ["ACCA", 1]]} 

1注意,h[k] =是用於該方法Hash#[]=語法糖,而h[k]上平等的右邊是方法Hash#[]

0

我不會回答你的功課,但這裏的一些你的僞代碼:

output = {} 

yourarray.each { |item| 
    // Key will be "IT" for the first iteration 
    key = item[0]; 
    // Value will be "Testing" for the first iteration 
    value = item[1]; 
    // Now you want to set Output['IT'] to 1 
    // If Output['IT'] was already set, then you need to increment the number 
} 
+0

這不是我的作業! –

1

你想的不太一樣,但我敢肯定,這將幫助:

arr.group_by(&:first).transform_values { |arr| arr.map { |sub| sub.last } 
                .group_by(&:itself) 
                .map { |k,v| [k, v.size] } 
             } 


#=> { "IT"   => [["Testing", 3], 
#      ["Banking Software", 1], 
#      ["ERP", 2], 
#      ["IT Security", 2]], 
#  
#  "Accounting" => [["Offshore", 1], 
#      ["ACCA", 1]] 
# } 

你可以把它推到一個數組中,我猜想Bob是你的叔叔。


主要方法:transform_values; group_bymap。有關更多信息,請參閱www.ruby-doc.org