2014-02-11 123 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"] 
# } 
# }