TransWikia.com

Rubyist way to test for a hash key in an array

Stack Overflow Asked by Lucky on November 12, 2021

I am parsing some JSON which has been converted to Ruby data structures. I have records that look either like this:

"uros"=>[{"ure"=>"zip*less", "prs"=>[{"mw"=>"ˈzip-ləs", "sound"=>{"audio"=>"ziples01", "ref"=>"c", "stat"=>"1"}}]

or like this:

"uros"=>[{"ure"=>"gas chromatographic", "fl"=>"adjective"}]

I want to pull out the hash value for the key audio when it appears.

What is the clean way to test for the presence of said key in Ruby? Here are my attempts thus far. The variable entry represents the enclosing data structure:

if entry["uros"] != nil # Nope              
#if entry["uros"]["prs"] != nil  # Nope 
#if not entry["uros"]["prs"]["sound"]["audio"].first.instance_of? nil  # Nope 
#if ! entry["uros"]["prs"].instance_of? nil  # Nope 

    puts entry["uros"].first["prs"].first["sound"]["audio"]

end

The error message I get is either:

undefined method `first' for nil:NilClass (NoMethodError)

or conversely:

 undefined method `[]' for nil:NilClass (NoMethodError)

How would you do this?

2 Answers

You can use the safe navigation operator to search around the the data structure without getting a bunch of NoMethodErrors. The safe navigation operator will call the method, or return nil if called on nil.

audio = entry["uros"]
  &.first
  &.[]("prs")
  &.first
  &.dig("sound", "audio")

This might look funny, but remember that [] is just another method. If any part of that method chain returns nil, the whole thing will return nil.

entry["uros"]&.first is roughly equivalent to...

entry["uros"].first if entry["uros"] != nil

Answered by Schwern on November 12, 2021

Hash has a method for checking presence of a key-value pair

if entry.key?('uros')

But problem with your code is you don't check for existence of the nested keys. You check for "uros", but then "prs" might not exist.

Here's a better version that allows nils at every step

audio = entry.dig('uros', 0, 'prs', 0, 'sound', 'audio')

Answered by Sergio Tulentsev on November 12, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP