2014-02-11 163 views
0

我已經完成了很長一段時間,因此這讓我感到困惑不已。我下面收集來自不同地方的數據,並希望把以下格式:哈希陣列(autovivification ??)

{ 
    :"user_100" => { 
     :user_policy => [ 
     "userpolicy_100", 
     "userpolicy_200" 
     ], 
     :group_policy => [ 
     "grouppolicy_300", 
     "grouppolicy_400" 
     ], 
    }, 
    :"user_200" => { 
     :user_policy => [ 
     "userpolicy_300", 
     "userpolicy_400" 
     ], 
     :group_policy => [ 
     "grouppolicy_300", 
     "grouppolicy_400" 
     ], 
    }, 
} 

上述結構是數組的哈希散列和我只是無法在Ruby中得到這個工作。順便說一句,我已經手動編寫了上述代碼,因此可能存在語法錯誤。

我想:

hash = Hash.new{ |h,k| h[k] = Hash.new(&h.default_proc) } 

,但是當我有nested hashesno array在路上這隻會工作。

然後我嘗試:

hash = Hash.new{ |h,k| h[k] = [] } 

,但這樣的工作只爲hash of arrays而不是hash of hash of array

我需要在一個地方捕獲這些數據,我想像上面的代碼片段中所顯示的那樣進行perl方式。

問:

  1. 如何在Ruby中創建hash of hash of array
  2. 是否有更通用的方式來初始化任何深度嵌套散列/數組組合?
  3. 或者我不是以RUBY'ISH的方式思考,有沒有更好的方式來解決我的根本問題?

UPDATE:

這是我的實際代碼:

array_users = Array.new 
hash_user_polices = Hash.new{ |h,k| h[k] = [] } 

iam = Aws::IAM.new 

iam.list_users().each do |resp| 
    resp.users.each do |x| 
    array_users << x.user_name 
    end 
end 

array_users.each do |user| 
    iam.list_user_policies(:user_name => user).each do |resp| 
    resp.each do |x| 
     x.policy_names.each do |y| 
     hash_user_polices[:"#{user}"] << y.to_s 
     end 
    end 
    end 
end 

所以,

  1. 我得到的用戶列表,並把它放在array_users。然後我得到作爲array返回的各自的用戶策略(因此我迭代了x.policy_names.each do |y|)。

  2. 我真的很想擁有hash_user_polices[:"#{user}"][:user_policy] << y.to_s

  3. 但是由於我在紅寶石方面的專業知識有限,我只能在hash_user_polices[:"#{user}"] << y.to_s之後將其定義爲hash_user_polices = Hash.new{ |h,k| h[k] = [] }

  4. 我將寫一段代碼來獲得group_policies,因此當時我希望它有hash_user_polices[:"#{user}"][:group_policy] << y.to_s

總之,我取user list,在三個不同的API調用user policygroup policy和掙扎在一個地方這三個鞏固,這樣我可以做出一些道理出來。

+1

這完全取決於數據源(S)的結構。你能否展示他們? – BroiSatse

+0

@BroiSatse,請找到更新。謝謝。 – slayedbylucifer

回答

1

如果結構總是hash.hash.array,你可以使用的組合你的兩次嘗試:

hash = Hash.new do |oh,ok| 
    oh[ok] = Hash.new do |ih,ik| 
    ih[ik] = [] 
    end 
end 

就我個人而言,我不會使用哈希和數組來做到這一點; ruby有一個非常強大的對象模型,我會爲每個嵌套級別(特別是「用戶」級別,它似乎有一組定義良好的屬性)創建類。儘管如此,你可能會發現有點矯枉過正。

+0

是的,我想不出除哈希/數組之外的任何其他方式,因爲這在perl中相當簡單,而且我已經完成了多年。我知道Ruby人不像perl人那樣使用嵌套的散列/數組。只是我不知道在ruby中實現相同的方式會是更好的方式。 – slayedbylucifer

+0

你能指點我一些文檔,這將有助於我理解如何使用類實現這一點。 +1。 – slayedbylucifer

+0

我創建了一個要點,希望能夠說明我在重構過程中的思維過程。我只是在主旨上走得如此之遠。您可以從中獲取儘可能多的信息:https://gist.github.com/phluid61/8933665 –

1

你可以做這樣的(但是這是很難不知道說你的數據的結構)

iam = Aws::IAM.new 

array_users = iam.list_users.map(&:users).flatten.map(&:user_name) 

Hash[ 
    array_users.map do |user| 
    [ 
     user.to_sym, 
     { user_policy: iam.list_user_policies(:user_name => user).map(&:resp).flatten.map(&:policy_names).flatten.map(&:to_s), 
     group_policy: <group_policy logic> 
     } 
    [   
    end 
end ] 
+0

我試圖讓你的代碼工作,因爲它抱怨沒有方法存在,並糾正了一些語法錯誤。同時,你能解釋它在做什麼嗎? – slayedbylucifer

1

如何將代碼分解爲更容易理解的內容,直至變得容易?

def add_policy(hash, user, policy) 
    # create a subhash for the user key if the hash doesn't exist 
    hash[user] ||= {} 

    # get the policy key: :group_policy or :user_policy 
    # if policy_key can not be determined from the policy, 
    # you could pass an extra param for the policy_key 
    policy_key = (policy.include?("group") ? :group_policy : :user_policy) 

    # create an array for the user's policy if none exists 
    hash[user][policy_key] ||= [] 

    # push the policy into the array 
    hash[user][policy_key] << policy 

    hash 
end 



h = {} 
add_policy(h, "user_100", "userpolicy_100") 
add_policy(h, "user_100", "userpolicy_200") 
add_policy(h, "user_100", "grouppolicy_300") 
add_policy(h, "user_100", "grouppolicy_400") 
add_policy(h, "user_200", "userpolicy_300") 
add_policy(h, "user_200", "userpolicy_400") 
add_policy(h, "user_200", "grouppolicy_300") 
add_policy(h, "user_200", "grouppolicy_400") 

=> {"user_100"=> 
    {:user_policy=>["userpolicy_100", "userpolicy_200"], 
    :group_policy=>["grouppolicy_300", "grouppolicy_400"]}, 
"user_200"=> 
    {:user_policy=>["userpolicy_300", "userpolicy_400"], 
    :group_policy=>["grouppolicy_300", "grouppolicy_400"]}} 
+0

感謝您提供不同的方法。它完美的作品。但是,我會按照時間順序接受@Matty的回答(他在[gist](https://gist.github.com/phluid61/8933665)中提供了這個回答)。 +1爲您的時間和努力。 – slayedbylucifer

+0

@slayedbylucifer哈哈,當然,沒有概率:-)感謝您的體貼,難得看到! – Abdo

0
require 'xkeys' 

r={}.extend XKeys::Auto 
r[:user_100, :user_policy, :[]] = 'userpolicy_100' 
r[:user_100, :user_policy, :[]] = 'userpolicy_200' 
r[:user_100, :group_policy, :[]] = 'grouppolicy_300' 
r[:user_100, :group_policy, :[]] = 'grouppolicy_400' 
r[:user_200, :user_policy, :[]] = 'userpolicy_300' 
r[:user_200, :user_policy, :[]] = 'userpolicy_400' 
r[:user_200, :group_policy, :[]] = 'grouppolicy_300' 
r[:user_200, :group_policy, :[]] = 'grouppolicy_400' 
p r 
# { 
# :user_100=>{ 
#  :user_policy=>["userpolicy_100", "userpolicy_200"], 
#  :group_policy=>["grouppolicy_300", "grouppolicy_400"] 
# }, 
# :user_200=>{ 
#  :user_policy=>["userpolicy_300", "userpolicy_400"], 
#  :group_policy=>["grouppolicy_300", "grouppolicy_400"] 
# } 
# }