arrays - rails - ruby hash



如何使用Ruby 2.3中引入的`Array#dig`和`Hash#dig`? (2)

Ruby 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解決的:

如何避免NoMethodError在嵌套哈希中缺少元素,而不重複nil檢查?

Ruby Style:如何檢查嵌套的哈希元素是否存在


Answer #1

一種方法是結合splat操作符從一些未知文檔模型中讀取。

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

Answer #2

在我們的例子中,由於nil引用而導致的NoMethodError是我們在生產環境中看到的最常見的錯誤。

新的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對像模式 。)

同樣,在您的示例中,空字符串或類似“N / A”的內容,具體取決於有意義的內容:

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




hash