Sten Kin
Sten Kin

Reputation: 2615

Check if values for a key in a array of hash are defined?

I have an array of hashes like so

[ {a:nil,...}, {a:nil,...}, ... ]

I'd like to check to if the value for all elements or for a particular key in the hash array are nil.

I know you do this for a single hash like so

hash.values.include? nil

Is there a better way than having to iter through the array and checking each hash?

Upvotes: 2

Views: 3029

Answers (3)

Cary Swoveland
Cary Swoveland

Reputation: 110755

This also works, though I would recommend @sawa's solutions.

Code

def all_nil?(array)
  array.flat_map(&:values).compact.empty?
end

def each_all_nil?(array)
  array.map { |h| h.values.compact.empty? }
end

Examples

array = [{dog: nil, cat: nil, bird: nil}, {rhino: nil, dog: nil, bird: nil}]
all_nil?(array)              #=> true
each_all_nil?(array)         #=> [true, true]

array = [{dog: nil, cat: nil, bird: nil}, {rhino: nil, dog: "woof", bird: nil}]
all_nil?(array)              #=> false
each_all_nil?(array)         #=> [true, false]

Explanation

array = [{dog: nil, cat: nil, bird: nil}, {rhino: nil, dog: "woof", bird: nil}]

For all_nil?

a = array.flat_map(&:values) #=> [nil, nil, nil, nil, "woof", nil]
b = a.compact                #=> ["woof"]
b.empty?                     #=> false

For each_all_nil?

When mapping the first element of array:

a = array.first              #=> {:dog=>nil, :cat=>nil, :bird=>nil}
b = a.values                 #=> [nil, nil, nil]
c = b.compact                #=> []
c.empty?                     #=> true

Upvotes: 1

K M Rakibul Islam
K M Rakibul Islam

Reputation: 34336

"Is there a better way than having to iterate through the array and checking each hash?"

Yes, you can make use of the Ruby's Enumerable all? to avoid looping through the array and checking each hash. The following are the two examples:

1.9.3p286 :001 > a = [{:a=>nil, :b=>nil}, {:a=>nil, :c=>nil}, {:d=> 1, :e=>nil}]
 => [{:a=>nil, :b=>nil}, {:a=>nil, :c=>nil}, {:d=>1, :e=>nil}] 
1.9.3p286 :002 > a.all?{|h| h.values.all?(&:nil?)}
 => false 
1.9.3p286 :003 > a = [{:a=>nil, :b=>nil}, {:a=>nil, :c=>nil}]
 => [{:a=>nil, :b=>nil}, {:a=>nil, :c=>nil}] 
1.9.3p286 :004 > a.all?{|h| h.values.all?(&:nil?)}
 => true 

Upvotes: 1

sawa
sawa

Reputation: 168269

array.all?{|h| h.values.all?(&:nil?)}

For a particular key key:

array.all?{|h| h[key].nil?}

Upvotes: 8

Related Questions