使用 nils 迭代 ruby​​ 嵌套哈希?

发布于 2024-12-20 23:40:17 字数 1174 浏览 1 评论 0原文

假设我正在从 API 返回 JSON 嵌套哈希(或哈希数组)

@example = {"results" = > {{"poop" => "shoop"},{"foo" => {"shizz" => "fizz", "nizzle"=>"bizzle"}}}

上述嵌套哈希的 YAML 标记

  - poop: shoop
  - foo:
    shizz: fizz
    nizzle: bizzle

现在让我们使用 ActiveRecord 从哈希中创建一个数据库条目。这很好用。

Thing.create!(:poop  => @example["results"]["poop"],
                :shizz => @example["results"]["foo"]["shizz"],
                :nizzle=> @example["results"]["foo"]["nizzle"])

但是如果'foo'为空或nil怎么办?例如,如果API结果有一个带有“名字”、“姓氏”等的“人”散列,则“人”散列将如果没有数据,通常为空,这意味着其中的哈希值不存在。

@example = {"results" = > {{"poop" => "shoop"},{"foo" => nil }}

  Thing.create!(:poop  => @example["results"]["poop"],
                :shizz => @example["results"]["foo"]["shizz"],
                :nizzle=> @example["results"]["foo"]["nizzle"])

  NoMethodError: You have a nil object when you didn't expect it! 
  You might have expected an instance of Array. 
  The error occurred while evaluating nil.[]

处理这个问题的最佳方法是什么?

Let say I'm getting back a JSON nested hash (or array of hashes) from an API

@example = {"results" = > {{"poop" => "shoop"},{"foo" => {"shizz" => "fizz", "nizzle"=>"bizzle"}}}

YAML markup for the nested hash above

  - poop: shoop
  - foo:
    shizz: fizz
    nizzle: bizzle

Now lets go make a db entry with ActiveRecord from the hash. This works fine.

Thing.create!(:poop  => @example["results"]["poop"],
                :shizz => @example["results"]["foo"]["shizz"],
                :nizzle=> @example["results"]["foo"]["nizzle"])

But what if 'foo' is empty or nil? For example, if an API result has a "person" hash with "first name","last name" # etc, the "person" hash will usually be empty if there is no data, which means the hashes inside it don't exist.

@example = {"results" = > {{"poop" => "shoop"},{"foo" => nil }}

  Thing.create!(:poop  => @example["results"]["poop"],
                :shizz => @example["results"]["foo"]["shizz"],
                :nizzle=> @example["results"]["foo"]["nizzle"])

  NoMethodError: You have a nil object when you didn't expect it! 
  You might have expected an instance of Array. 
  The error occurred while evaluating nil.[]

What's the best way to handle this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

陌若浮生 2024-12-27 23:40:17

不久前我遇到了一个 nil 敏感的 Hash#get 方法。

class Hash
  def get(key, default=nil)
    key.split(".").inject(self){|memo, key_part| memo[key_part] if memo.is_a?(Hash)} || default
  end
end

h = { 'a' => { 'b' => { 'c' => 1 }}}
puts h.get "a.b.c"    #=> 1
puts h.get "a.b.c.d"  #=> nil
puts h.get "not.here" #=> nil

对于这种 JSON 钻探来说非常方便。

否则你必须做这样的事情:

h['a'] && h['a']['b'] && h['a']['b']['c']

那真是太糟糕了。

I came accross a nil sensitive Hash#get method a while back.

class Hash
  def get(key, default=nil)
    key.split(".").inject(self){|memo, key_part| memo[key_part] if memo.is_a?(Hash)} || default
  end
end

h = { 'a' => { 'b' => { 'c' => 1 }}}
puts h.get "a.b.c"    #=> 1
puts h.get "a.b.c.d"  #=> nil
puts h.get "not.here" #=> nil

It's pretty handy for this sort of JSON drilling.

Otherwise you have to do stuff like this:

h['a'] && h['a']['b'] && h['a']['b']['c']

And that just sucks.

九厘米的零° 2024-12-27 23:40:17

Ruby 2.3.0 引入了一种名为 dig 的新方法 上的 HashArray 完全解决了这个问题。

value = hash.dig(:a, :b)

如果任何级别的密钥丢失,它都会返回nil

Ruby 2.3.0 introduced a new method called dig on both Hash and Array that solves this problem entirely.

value = hash.dig(:a, :b)

It returns nil if the key is missing at any level.

女皇必胜 2024-12-27 23:40:17

如果您使用的是 Rails(不确定是否在 ruby​​ 1.9 中):

h = {"a"=>1}
h.try(:[],"a") #1
h.try(:[],"b") #nil

h2 = {"c"=>{"d"=>1}}
h2.try(:[],"c").try(:[],"d")   #1
h2.try(:[],"a").try(:[],"foo") #nil

# File activesupport/lib/active_support/core_ext/object/try.rb, line 28
def try(*a, &b)
  if a.empty? && block_given?
    yield self
  else
    __send__(*a, &b)
  end
end

If you're using rails (not sure if it's in ruby 1.9):

h = {"a"=>1}
h.try(:[],"a") #1
h.try(:[],"b") #nil

h2 = {"c"=>{"d"=>1}}
h2.try(:[],"c").try(:[],"d")   #1
h2.try(:[],"a").try(:[],"foo") #nil

# File activesupport/lib/active_support/core_ext/object/try.rb, line 28
def try(*a, &b)
  if a.empty? && block_given?
    yield self
  else
    __send__(*a, &b)
  end
end

尽揽少女心 2024-12-27 23:40:17

我继续并开始将所有哈希结果传递到 Hashie Mash 中。这样它们的行为就像 Ruby 对象一样,并且像冠军一样响应 nils!

I went ahead and started passing all Hash results into a Hashie Mash. That way they behave like Ruby objects and respond to nils like a champ!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文