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:第一个参数是整数索引或字符串头。