【问题标题】:How to find the key in hash by a key within its nested hash如何通过嵌套哈希中的键查找哈希中的键
【发布时间】:2020-06-24 11:51:34
【问题描述】:

有一个嵌套散列,我需要通过它里面的键找到第一级键。例如,

hash = {
  a: {
    first: 0,
    second: 1
  },
  b: {
    third: 2
  }
} 

我得到了:first,我需要找到它所属的密钥,在这种情况下它将是:a。提前致谢

【问题讨论】:

  • 多个“一级键[s]”是否可以包含搜索到的键?如果是这样,应该是什么反应?深度有保证吗?二级键是否也可以将Hash 结构引用到可能存在搜索键的第 n 级?如果是这样,“第一级键”是否仍然是返回值?

标签: ruby-on-rails ruby hash


【解决方案1】:

如果您希望多次询问散列,对于不同的内部键(:first:second 等),您可能希望在询问开始之前构造以下散列。

hash = { a: { first: 0, second: 1 }, b: { third: 2 } } 

h = hash.each_with_object({}) { |(k,v),h| v.each { |kk,_| h[kk] = k } }
  #=> {:first=>:a, :second=>:a, :third=>:b} 

以便稍后您可以简单地进行哈希查找:

h[:first]
  #=> :a

如果哈希看起来像这样:

hash = { a: { first: 0, second: 1 }, b: { third: 2, first: 3 } }

您可能希望将h 定义如下:

h = hash.each_with_object({}) do |(k,v),h|
  v.each { |kk,_| h.update(kk=>[k]) { |_,o,n| o+n } }
end
  #=> {:first=>[:a, :b], :second=>[:a], :third=>[:b]}

这使用Hash#update(又名merge!)的形式,它使用一个块(此处为{ |_,o,n| o+n })来确定在被合并的两个哈希中存在的键的值。有关三个块变量_on 的解释,请参阅文档。我将_ 用于保存公共密钥的变量,以告诉读者它没有用于块计算。这是常见的做法,尽管您可能会看到,例如,_key 代替了_

【讨论】:

    【解决方案2】:

    您可以使用Enumerable#findHash#key?

    Hash[*hash.find { |_, value| value.key?(:first) }]
    # {:a=>{:first=>0, :second=>1}}
    

    确实,作为一个哈希,您可以在“主”哈希内的不同哈希中拥有相同的键,所以select 可能也是一个选项。

    【讨论】:

    • 非常感谢!这对我有用。我可以问为什么我们在哈希前面使用 * 吗? @sebastian-palma
    • 我认为 OP 正在寻找:a,即hash.find { |_, value| value.key?(:first) }.first
    • 用于将内容“扩展”为Hash::[] 的参数数组,类似于将hash.find { ... } 包装为数组Hash[[hash.find { |_, value| value.key?(:first) }]]@unnamed_road。
    • 路,g = hash.find { |_, value| value.key?(:first) } #=> [:a, {:first=>0, :second=>1}]。如果您检查文档Hash::[],您会发现您可以写成Hash[*g] #=> {:a=>{:first=>0, :second=>1}}Hash[[g]] #=> {:a=>{:first=>0, :second=>1}}。在第一种情况下,splat 运算符* 导致Hash[*g] 被评估Hash[:a, {:first=>0, :second}],这是可以使用(类)方法Hash::[] 的方式之一。
    【解决方案3】:

    您可以提取keys,然后提取find,其中hash 有一个名为:first 的键:

    hash.keys.find { |k| hash[k].key?(:first) }
    #=> :a
    

    使用select 而不是find 来获取所有匹配键的数组(如果可以有多个)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-07-07
      • 1970-01-01
      • 1970-01-01
      • 2017-08-02
      • 2021-12-08
      • 2014-01-30
      • 1970-01-01
      相关资源
      最近更新 更多