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:第一个参数是 Integer 索引。 -
Hash#dig:第一个参数是键。 -
Struct#dig:第一个参数是键。
在标准库部分
-
OpenStruct#dig:第一个参数是 String 名称。
-
CSV::Table#dig:第一个参数是 Integer 索引或 String 头部。
-
CSV::Row#dig:第一个参数是 Integer 索引或 String 头部。