Ruby [写给一些还不知道的 PG 们] Array#dig, Hash#dig, OpenStruct#dig, New features in ruby 2.3

zfjoy520 · 2016年05月12日 · 最后由 _kaichen 回复于 2016年05月16日 · 3533 次阅读

原文:https://blog.blockscore.com/new-features-in-ruby-2-3/ discussion: http://stackoverflow.com/questions/34346653/how-do-i-use-arraydig-and-hashdig-introduced-in-ruby-2-3

Array#dig, Hash#dig, OpenStruct#dig in ruby 2.3, 抛弃老旧的 xx[:a][:b][:c], xx.fetch(:a, {}).fetch(:b, {}).fetch(:c, nil) 吧

Array

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

Hash

user = {
  user: {
    address: {
      street1: '123 Main street'
    }
  }
}

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

OpenStruct

address = OpenStruct.new('city' => "Anytown NC", 'zip' => 12345)
person = OpenStruct.new('name' => 'John Smith', 'address' => address)
person.dig(:address, 'zip') # => 12345
person.dig(:business_address, 'zip') # => nil

低版本 ruby patch

class Array
  def dig(index, *indices)
    Array[index, indices].flatten.inject(self) { |result, index| result.send(:[], index) rescue nil }
  end unless Array.method_defined?(:dig)
end

class Hash
  def dig(name, *names)
    Array[name, names].flatten.inject(self) { |result, name| result.send(:[], name) rescue nil }
  end unless Hash.method_defined?(:dig)
end

class OpenStruct
  def dig(name, *names)
    begin
      name = name.to_sym
    rescue NoMethodError
      raise TypeError, "#{name} is not a symbol nor a string"
    end
    @table.dig(name, *names)
  end unless OpenStruct.method_defined?(:dig)
end

也可以将 Array 和 Hash 合成一个,因为他们都 include Enumerable

module Enumerable
  def dig(arg, *args)
    Array[arg, args].flatten.inject(self) { |result, arg| result.send(:[], arg) rescue nil }
  end unless Enumerable.method_defined?(:dig)
end

dig 好东西

已加入肯德基豪华午餐

我感觉不需要两个参数呢,可以就用一个数组参数就行。把最后在Enumerable里面的方法改写了下:

module Enumerable
  def dig(*args)
    args.inject(self) { |result, arg| result.send(:fetch, arg) }
  rescue
    return nil
  end
end

不用inline rescue,是因为它会有不必要的对 nil 的不断的方法调用和不断的 rescue 处理。

#3 楼 @hiveer 赞。 其实用两个参数,只是为了在不传参数的时候抛出异常,用数组参数,是可以不传参数的哟。

看到题目的时候还在想 Postgres 和 Array#dig 有什么关系呢

需要 登录 后方可回复, 如果你还没有账号请 注册新账号