如何在嵌套哈希中搜索特定键的值?

时间:2017-03-09 09:21:57

标签: ruby hash key

说我有这样的哈希:

[82] pry(main)> commit2
=> {:sha=>"4df2b779ddfcb27761c71e00e2b241bfa06a0950",
 :commit=>
  {:author=>
    {:name=>"asasa asasa",
     :email=>"asa@asasad.com",
     :date=>2016-08-06 16:24:04 UTC,
     :sha=> "876239789879ab9876c8769287698769876fed"},
   :committer=>
    {:name=>"asasa asasa",
     :email=>"asa@asasad.com",
     :date=>2016-08-06 16:26:45 UTC},
   :message=>
    "applies new string literal convention in activerecord/lib\n\nThe current code base is not uniform. After some discussion,\nwe have chosen to go with double quotes by default.",
   :tree=>
    {:sha=>"7a83cce62195f7b20afea6d6a8873b953d25cb84",
     :url=>
      "https://api.github.com/repos/rails/rails/git/trees/7a83cce62195f7b20afea6d6a8873b953d25cb84"},
   :url=>
    "https://api.github.com/repos/rails/rails/git/commits/4df2b779ddfcb27761c71e00e2b241bfa06a0950",
   :comment_count=>0},
 :url=>
  "https://api.github.com/repos/rails/rails/commits/4df2b779ddfcb27761c71e00e2b241bfa06a0950",
 :html_url=>
  "https://github.com/rails/rails/commit/4df2b779ddfcb27761c71e00e2b241bfa06a0950",
 :comments_url=>
  "https://api.github.com/repos/rails/rails/commits/4df2b779ddfcb27761c71e00e2b241bfa06a0950/comments"
     }
   }
 } 

此哈希有许多嵌套哈希,但我想查看是否有任何嵌套哈希的:sha值为876239789879ab9876c8769287698769876fed

在上面的示例中,它应该返回[:commit][:author]哈希值,因为该哈希值具有:sha键,其值与我们要查找的值相同。

我该怎么做?

1 个答案:

答案 0 :(得分:2)

这是一个递归方法:

data = {a: {b: :c, d: :e}, f: {g: {h: {i: :j}}}}

def find_value_in_nested_hash(data, desired_value)
  data.values.each do |value| 
    case value
    when desired_value
      return data
    when Hash
      f = find_value_in_nested_hash(value, desired_value)
      return f if f
    end
  end
  nil
end

p find_value_in_nested_hash(data, :e)
# {b=>:c, :d=>:e}

用你的例子:

repo = { sha: '4df2b779ddfcb27761c71e00e2b241bfa06a0950',
         commit: { author:  { name: 'asasa asasa',
                              email: 'asa@asasad.com',
                              date: '2016-08-06 16:24:04 UTC',
                              sha: '876239789879ab9876c8769287698769876fed' },
                   committer:  { name: 'asasa asasa',
                                 email: 'asa@asasad.com',
                                 date: '2016-08-06 16:26:45 UTC' },
                   message:  "applies new string literal convention in activerecord/lib\n\nThe current code base is not uniform. After some discussion,\nwe have chosen to go with double quotes by default.",
                   tree:  { sha: '7a83cce62195f7b20afea6d6a8873b953d25cb84',
                            url:  'https://api.github.com/repos/rails/rails/git/trees/7a83cce62195f7b20afea6d6a8873b953d25cb84' },
                   url:  'https://api.github.com/repos/rails/rails/git/commits/4df2b779ddfcb27761c71e00e2b241bfa06a0950',
                   comment_count: 0 },
         url:  'https://api.github.com/repos/rails/rails/commits/4df2b779ddfcb27761c71e00e2b241bfa06a0950',
         html_url:  'https://github.com/rails/rails/commit/4df2b779ddfcb27761c71e00e2b241bfa06a0950',
         comments_url:  'https://api.github.com/repos/rails/rails/commits/4df2b779ddfcb27761c71e00e2b241bfa06a0950/comments' }

p find_value_in_nested_hash(repo, '876239789879ab9876c8769287698769876fed')
#=> {:name=>"asasa asasa", :email=>"asa@asasad.com", :date=>"2016-08-06 16:24:04 UTC", :sha=>"876239789879ab9876c8769287698769876fed"}