【发布时间】:2021-03-21 21:14:43
【问题描述】:
有没有一种“简单”的方法,除了手写Hash#dig 执行的那种嵌套哈希/数组遍历,我可以确定一个键是否存在于深度嵌套的哈希中?另一种询问方式是说“确定是否分配了任何值”。
没有分配任何内容的 Hash 与明确分配了 nil 之间存在差异 - 特别是如果 Hash 是使用与 nil 不同的缺失键默认值构造的!
h = { :one => { :two => nil }}
h.dig(:one, :two).nil? # => true; but :two *is* present; it is assigned "nil".
h[:one].key?(:two) # => true, because the key exists
h = { :one => {}}
h.dig(:one, :two).nil? # => true; :two *is not* present; no value is assigned.
h[:one].key?(:two) # => FALSE, because the key does not exist
【问题讨论】:
-
stackoverflow.com/questions/1820451/… 可能是一种方式。 stackoverflow.com/questions/15031412/… 是另一个。简短的回答是否定的,没有。你的用例是什么?
-
第一个最终建议使用#dig 和另外两个手动编码Ruby 迭代器(在这些情况下,它不处理数组,因此无论如何在功能上不等同于#dig)。用例是一个复杂的嵌套哈希/数组入站有效负载,通过模式对象递归迭代,提供到线性属性集的所有可能映射,路径数组保持位置。我可以手写一种“#dig?”,它会很优雅,但我很可能只是重新设计迭代器方法,使其不那么优雅,但维护成本也更低,而不是这样做。
-
更具体一点:这是一个 SCIM v2 实现,它利用了 ScimEngine、ScimRails 和 SCIM Query Filter Parser 中先前但所有情况下不完整的工作,以提供更全面的解决方案。手头的问题来自tools.ietf.org/html/rfc7644#section-3.5.1 描述的 PUT 语义,我希望在其中保持“可能假定客户端不断言”行为。一旦功能完成并经过测试,我们将在 MIT 许可下发布这项工作。
-
让我们让您的问题更准确。如果
h = { :one => { :two => { :four => nil }, :three => { :five => nil } } }你可能会问是否有一个嵌套散列,比如:four是一个键。您可以使用递归来确认是否存在这样的密钥,并且如果需要,可以生成一个向下钻取的密钥序列。但这不是你要问的。您的问题可能是“h是否有一个键:one,其值是具有键:two的散列,其值是具有键:four的散列?”。您可以轻松地将其转换为代码,使用dig或不使用... -
...使用
dig,g = h.dig(:one, :two); g.is_a?(Hash) && g.key?(:four)。