Dig 方法¶ ↑
Ruby 的 dig
方法对于访问嵌套数据结构非常有用。
考虑以下数据
item = { id: "0001", type: "donut", name: "Cake", ppu: 0.55, batters: { batter: [ {id: "1001", type: "Regular"}, {id: "1002", type: "Chocolate"}, {id: "1003", type: "Blueberry"}, {id: "1004", type: "Devil's Food"} ] }, topping: [ {id: "5001", type: "None"}, {id: "5002", type: "Glazed"}, {id: "5005", type: "Sugar"}, {id: "5007", type: "Powdered Sugar"}, {id: "5006", type: "Chocolate with Sprinkles"}, {id: "5003", type: "Chocolate"}, {id: "5004", type: "Maple"} ] }
没有 dig
方法,你可以这样写
item[:batters][:batter][1][:type] # => "Chocolate"
使用 dig
方法,你可以这样写
item.dig(:batters, :batter, 1, :type) # => "Chocolate"
没有 dig
方法,你可以这样写,但会出错(抛出 NoMethodError (undefined method `[]' for nil:NilClass)
)
item[:batters][:BATTER][1][:type]
使用 dig
方法,你可以这样写(仍然会出错,但避免了异常)
item.dig(:batters, :BATTER, 1, :type) # => nil
为什么 dig
更好?¶ ↑
-
它具有更少的语法元素(不容易出错)。
-
它读起来更好。
-
如果找不到项目,它不会引发异常。
dig
如何工作?¶ ↑
调用顺序是
obj.dig(*identifiers)
identifiers
定义了嵌套数据结构中的“路径”。
-
对于
identifiers
中的每个标识符,都会在接收器上调用方法 #dig,并使用该标识符作为参数。 -
第一个接收器是
self
。 -
每个后续接收器都是前一次调用
dig
返回的值。 -
最终返回的值是最后一次调用
dig
返回的值。
如果任何接收器没有响应 #dig,dig
方法会引发异常。
h = { foo: 1 } # Raises TypeError (Integer does not have #dig method): h.dig(:foo, :bar)
还有什么?¶ ↑
上面的结构包含 Hash 对象和 Array 对象,它们都具有实例方法 dig
。
总共有六个内置的 Ruby 类具有 dig
方法,其中三个在核心类中,三个在标准库中。
在核心类中
-
Array#dig
:第一个参数是整数索引。 -
Hash#dig
:第一个参数是键。 -
Struct#dig
:第一个参数是键。
在标准库中
-
OpenStruct#dig:第一个参数是字符串名称。
-
CSV::Table#dig:第一个参数是整数索引或字符串标题。
-
CSV::Row#dig:第一个参数是整数索引或字符串标题。