2013-12-19 39 views
0

我有散列其值是散列的数组的数组:嵌套在散列阵列的元件的位置

org_array = [] 
#Create Parents 
org_array.push(:org_name => "Parent 1", :org_id => "123ABC", :org_parent_id => nil,  :children => [], :status => "created") 
org_array.push(:org_name => "Parent 2", :org_id => "456ABC", :org_parent_id => nil, :children => [], :status => "created") 
org_array.push(:org_name => "Parent 3", :org_id => "789ABC", :org_parent_id => nil, :children => [], :status => "created") 
org_array.push(:org_name => "Parent 4", :org_id => "1011ABC", :org_parent_id => nil, :children => [], :status => "created") 
#Create Children 
org_array[0][:children].push(:org_name => "Child1", :org_id => "1234ABC", :org_parent_id => "123ABC", :children => [], :status => "created") 
org_array[0][:children].push(:org_name => "Child2", :org_id => "5678ABC", :org_parent_id => "123ABC", :children => [], :status => "created") 
org_array[0][:children].push(:org_name => "Child3", :org_id => "91011ABC", :org_parent_id => "123ABC", :children => [], :status => "created") 
org_array[1][:children].push(:org_name => "Child1", :org_id => "1213ABC", :org_parent_id => "456ABC", :children => [], :status => "created") 
org_array[1][:children].push(:org_name => "Child2", :org_id => "1415ABC", :org_parent_id => "456ABC", :children => [], :status => "created") 
#Create Grandchildren 
org_array[0][:children][0][:children].push(:org_name => "Granchild1", :org_id => "1617ABC", :org_parent_id => "1234ABC", :children => [], :status => "created") 
org_array[0][:children][1][:children].push(:org_name => "Granchild2", :org_id => "1617ABC", :org_parent_id => "5678ABC", :children => [], :status => "created") 
org_array[0][:children][2][:children].push(:org_name => "Granchild3", :org_id => "1819ABC", :org_parent_id => "91011ABC", :children => [], :status => "created") 
org_array[1][:children][0][:children].push(:org_name => "Granchild1", :org_id => "1920ABC", :org_parent_id => "1213ABC", :children => [], :status => "created") 
org_array[1][:children][1][:children].push(:org_name => "Granchild2", :org_id => "2122ABC", :org_parent_id => "1415ABC", :children => [], :status => "created") 

以下代码返回的对象和键:

def nested_hash_value(obj, key, value) 
    if obj.respond_to?(:key?) && obj.key?(key) && obj.has_value?(value) 
    return obj[key] 
    elsif obj.respond_to?(:each)#checks to see if its an array 
    r = nil 
    obj.find{ |*a|r=nested_hash_value(a.last ,key, value)} 
    r 
    end 
end 

nested_hash_value(org_array, :org_id, "2122ABC") 

但我希望它返回对象的位置,如org_array[1][:children][1][:children][0]而不是值2122ABC

+1

我想你应该解释为什么/什么你想要这样做。获取对象的id可能会更好,然后能够在以后重新引用它 –

+0

我希望能够找到更新状态键的对象,或者能够将更多组织作为子组织单击到任何位置父母/子女/孙子女组织无论组织架构如何,只要我拥有org_id。 –

+0

重新评论我的回答,我不明白你是如何使用'inject',考虑到它需要一个块和一个可选的初始值作为参数。 –

回答

1
def nested_hash_value(arr, key, val, path_arr = []) 
    return nil if arr.empty? 
    arr.each_with_index do |h,i|  
    return path_arr << i if h.key?(key) && h[key] == val 
    if h.key?(:children) && rv = nested_hash_value(arr[i][:children], \ 
     key, val, path_arr.dup << i << :children) 
     return rv 
    end   
    end 
    return nil 
end 

p nested_hash_value(org_array, :org_id, "2122ABC") 
    # => [1, :children, 1, :children, 0] 
p nested_hash_value(org_array, :org_id, "1819ABC") 
    # => [0, :children, 2, :children, 0] 
p nested_hash_value(org_array, :org_id, "789ABC") 
    # => [2] 
p nested_hash_value(org_array, :org_id, "91011ABC") 
# => [0, :children, 2] 

因为你是新来的描述符Stackoverflow(SO),我想就你提出的问题提出几点建议,你可能希望在将来应用这些建议:

  • 删除所有不是问题核心的散列字段;
  • 将儿童和孙子的数量减少到插图所需的最小数量;和
  • 而不是显示构造数组的代码,显示数组本身,以澄清其结构的方式。如果一行太长显示,如果完全与水平滚动,插入续行符

    org_array = 
        [{:org_id=>"123ABC", :org_parent_id => nil, :children => 
         [{:org_id=>"1234ABC", :org_parent_id=>"123ABC", :children => 
          [{:org_id=>"1617ABC", :org_parent_id=>"1234ABC", :children => []}] 
         }, 
         {:org_id=>"5678ABC", :org_parent_id=>"123ABC", :children => 
          [{:org_id=>"1617ABC", :org_parent_id=>"5678ABC", :children => []}] 
         } 
         ] 
        }, 
        {:org_id=>"456ABC", :org_parent_id => nil, :children => 
         [{:org_id=>"1213ABC", :org_parent_id=>"456ABC", :children => 
          [{:org_id=>"1920ABC", :org_parent_id=>"1213ABC", :children => []}] 
         }, 
         {:org_id=>"1415ABC", :org_parent_id=>"456ABC", :children => 
          [{:org_id=>"2122ABC", :org_parent_id=>"1415ABC", :children => []}] 
         } 
         ] 
        } 
        ] 
    

应用这些原则,你可以用下面的开始。假装这条线是很长的,如果不继续说道:

{:org_id => "1415ABC", :org_parent_id => "456ABC", \ 
     :children => 

你可能会考虑在你的代码是这样定义orig_arr,而不是所有的推语句(除非它被动态构建,当然)。

现在让我们来考虑一下,改变数组org_array的结构是否有帮助。考虑到数组索引实际上没有任何用处,您可以考虑将其作为散列哈希的散列,并使用散列键:org_id。 (请注意,Grandchild1和Grandchild2具有相同的:org_id。这不是问题,因为他们的父母(Child1和Child2)拥有不同的密钥,但我不知道您是否打算这么做。)

对父ID的反向引用通常不是必需的,因为后者在您需要时可用,或者可以在运行中轻松计算。你可能会考虑类似下面的哈希值,它包含了所有在你的org_array的信息字段:

org_hash = 
    {"123ABC" => {:org_name => "Parent 1", :status => "created", :children => 
    {"1234ABC" => {:org_name => "Child1", :status => "created", :children => 
     {"1617ABC" => {:org_name => "Grandchild1", :status => "created"}}}, 
     "5678ABC" => {:org_name => "Child2", :status => "created", :children => 
     {"1617ABC" => {:org_name => "Grandchild2", :status => "created"}}}}}, 
    "456ABC" => {:org_name => "Parent 2", :status => "created", :children => 
    {"1213ABC" => {:org_name => "Child1", :status => "created", :children => 
     {"1920ABC" => {:org_name => "Grandchild1", :status => "created"}}}, 
     "1415ABC" => {:org_name => "Child2", :status => "created", :children => 
     {"2122ABC" => {:org_name => "Grandchild2", :status => "created"}}}}} 
    } 

会定义org_hash这样使生活更轻松吗?

顺便说一句,您可能会熟悉一些可以对复杂对象进行格式化的“漂亮打印”宝石,例如org_arrayorg_hash。一个这样的宝石是Awesome Print,你将调用如下:

require 'ap' 
ap org_hash 

这将显示如下(我已经母公司1后截断):

{ 
    "123ABC" => { 
     :org_name => "Parent 1", 
      :status => "created", 
     :children => { 
      "1234ABC" => { 
       :org_name => "Child1", 
        :status => "created", 
       :children => { 
        "1617ABC" => { 
         :org_name => "Grandchild1", 
          :status => "created" 
        } 
       } 
      }, 
      "5678ABC" => { 
       :org_name => "Child2", 
        :status => "created", 
       :children => { 
        "1617ABC" => { 
         :org_name => "Grandchild2", 
          :status => "created" 
        } 
       } 
      } 
     } 
    }, 
... 
+0

This Works!为了更新搜索结果的值,我使用了inject命令,例如这会改变org_name的名字,找到'p.inject(org_array,:fetch)[:org_name] =“New Name” ' –

0

我想你应该考虑通过生产在目前的“位置”所需的关键数据结构

def nested_hash_value(obj, key, value, keychain=[]) 
    keychain << key 

    if obj.respond_to?(:key?) && obj.key?(key) && obj.has_value?(value) 
    return keychain 
    elsif obj.respond_to?(:each) # checks to see if its an array 
    r = nil 
    obj.find{ |*a| r=nested_hash_value(a.last ,key, value, keychain) } 
    r 
    end 
end 

nhv_result = nested_hash_value(org_array, :org_id, "2122ABC") 

注:我认为这将输出类似

#=> nhv_result 
[1, :children, 1, :children, 0] 

但它还没有。我工作的一个改进,但是这显然是一个可行的方法


那么你的结果是如何找到价值再次

nhv_result.reduce(org_array) {|acc, key| acc = acc[key] } 
+0

我同意,但我尝试了这样的事情,并得到了与此代码生成的结果相同的结果:org_id org_id org_id ... –