如何使用Ruby的2.3引入了阵列#挖掘和Hash#挖?

问题描述 投票:32回答:3

红宝石2.3介绍了ArrayHash称为dig的新方法。我在有关新发布的博客文章中看到的例子是做作难懂:

# Hash#dig
user = {
  user: {
    address: {
      street1: '123 Main street'
    }
  }
}

user.dig(:user, :address, :street1) # => '123 Main street'

# Array#dig
results = [[[1, 2, 3]]]
results.dig(0, 0, 0) # => 1

我不使用三层嵌套的平阵列。什么的怎样,这将是有用的一个现实的例子吗?

UPDATE

事实证明,这些方法解决最常问的Ruby的问题之一。下面的问题有类似20个副本,所有这些都通过使用dig解决:

How to avoid NoMethodError for missing elements in nested hashes, without repeated nil checks?

Ruby Style: How to check whether a nested hash element exists

arrays ruby hash
3个回答
62
投票

在我们的例子,NoMethodErrors由于nil引用是迄今为止我们在生产环境中看到的最常见的错误。

Hash#dig允许您访问嵌套元素时省略nil检查。由于哈希值是最适合用于当数据的结构是未知的,或易挥发,有官方的支持,这使得有很大的意义。

让我们把你的例子。下列:

user.dig(:user, :address, :street1)

不等同于:

user[:user][:address][:street1]

user[:user]user[:user][:address]nil的情况下,这将导致运行时错误。

相反,它是等效于以下内容,这是当前成语:

user[:user] && user[:user][:address] && user[:user][:address][:street1]

注意它是如何微不足道的传递是在别处创建成Hash#dig符号列表,而不是非常简单,从这样一个列表重新后者构造。 Hash#dig让您轻松做动态访问,而不必担心nil引用。

显然Hash#dig也短了很多。


采取的笔记很重要的一点是,Hash#dig自己返回nil如果任何按键变成是,这可能会导致同一类错误的一步向下行的,所以它可以是一个好主意,提供一个合理的默认。 (提供对象,它总是响应于预期被称为Null Object Pattern方法的这种方式。)

同样,在你的榜样,一个空字符串或类似“N / A”,这取决于情理之中的事情:

user.dig(:user, :address, :street1) || ""

9
投票

一种方法是与图示操作者从一些不知名的文档模型一起阅读。

some_json = JSON.parse( '{"people": {"me": 6, ... } ...}' )
# => "{"people" => {"me" => 6, ... }, ... }
a_bunch_of_args = response.data[:query]
# => ["people", "me"]
some_json.dig(*a_bunch_of_args)
# => 6

1
投票

这是通过深度嵌套的散列/阵列,这可能是你会得到什么从API回电,例如工作的方式非常有用。

从理论上讲,可以节省一吨的代码,否则将层层把关另一个层面是否存在,否则,你的风险不断错误。在实践中,你可能仍然需要大量的代码作为dig仍然会在某些情况下,创建错误(例如,如果链中的任何一个不带键的对象。)

正是出于这个原因,你的问题其实是真的有效 - dig还没有看到我们所期望的使用。这是在这里评论例如:Why nobody speaks about dig

为了使dig避免这些错误,请尝试KeyDial宝石,这是我写的环绕dig并迫使它,如果任何错误影响了返回零/默认。

© www.soinside.com 2019 - 2024. All rights reserved.