Reputation: 471
I need to get all values of 'name' keys and at the same time to get values of 'children' keys. I'm able to retrieve only 'names' from first level but stuck with 'children' since not all 'names' have them.
puts data['labels'].collect { |item| item['name'] }
The JSON response is the following:
{"labels": [{
"name": "Crime"
}, {
"name": "Demonstrations"
}, {
"name": "Music",
"children": [{
"name": "Awards"
}, {
"name": "Classical"
}, {
"name": "Country"
}, {
"name": "Other"
}, {
"name": "Pop"
}, {
"name": "Soul"
}, {
"name": "X Factor"
}]
}, {
"name": "Politics"
}, {
"name": "Rescue"
}, {
"name": "Special Events"
}, {
"name": "Sports",
"children": [{
"name": "Auto Racing"
}, {
"name": "Awards"
}, {
"name": "Baseball"
}, {
"name": "Basketball"
}, {
"name": "NASCAR (Cup)"
}, {
"name": "NASCAR (Nationwide)"
}, {
"name": "NASCAR (Truck)"
}, {
"name": "NASCAR (XFINITY)"
}, {
"name": "Other"
}, {
"name": "Rodeo"
}, {
"name": "Rugby"
}, {
"name": "Running"
}, {
"name": "Sailing"
}, {
"name": "Skating"
}, {
"name": "Volleyball"
}]
}, {
"name": "Traffic"
}, {
"name": "Weather"
}]}
Upvotes: 0
Views: 99
Reputation: 52377
puts data['labels'].collect { |item| item['name'] }
Will throw an error
NoMethodError: undefined method `map' for nil:NilClass
since your keys are symbols, not strings.
Also
and at the same time to get values of 'children' keys
Are you sure you want to get keys? Because all keys are identical (:name
). May be you need values? Anyway, if you need keys, just change the values
to keys
in below solution.
Now solution (using safe navigator (&
)):
data[:labels].map { |item| [item[:name], item[:children]&.map(&:values)] }
# => [["Crime", nil],
# ["Demonstrations", nil],
# ["Music", ["Awards", "Classical", "Country", "Other", "Pop", "Soul", "X Factor"]],
# ["Politics", nil],
# ["Rescue", nil],
# ["Special Events", nil],
# ["Sports", ["Auto Racing", "Awards", "Baseball", "Basketball", "NASCAR (Cup)", "NASCAR (Nationwide)", "NASCAR (Truck)", "NASCAR (XFINITY)", "Other", "Rodeo", "Rugby", "Running", "Sailing", "Skating", "Volleyball"]],
# ["Traffic", nil],
# ["Weather", nil]
# ]
The above solution without using safe navigator:
data[:labels].map { |item| [item[:name], item[:children] ? item[:children].map(&:values) : nil] }
Upvotes: 2
Reputation: 110755
If h
is your hash, you could write
h[:labels].map do |f|
g = { name: f[:name] }
f.key?(:children) ? g.merge(children: f[:children].flat_map(&:values)) : g
end
#=> [{:name=>"Crime"},
# {:name=>"Demonstrations"},
# {:name=>"Music",
# :children=>["Awards", "Classical", "Country", "Other", "Pop", "Soul", "X Factor"]
# },
# {:name=>"Politics"},
# {:name=>"Rescue"},
# {:name=>"Special Events"},
# {:name=>"Sports",
# :children=>["Auto Racing", "Awards", "Baseball", "Basketball", "NASCAR (Cup)",
# "NASCAR (Nationwide)", "NASCAR (Truck)", "NASCAR (XFINITY)", "Other",
# "Rodeo", "Rugby", "Running", "Sailing", "Skating", "Volleyball"]
# },
# {:name=>"Traffic"},
# {:name=>"Weather"}
# ]
This uses the methods Hash#key?, Hash#merge, Enumerable#flat_map and a few more common ones.
Upvotes: 1