Richlewis
Richlewis

Reputation: 15374

Comparing a hashes value against array in order

If I have the following hash and array

hash  = {'i' => 'i', 'av' => 'av', 'deviceName' => 'Genymotionvbox86p'}
array = ['i', 'av', 'Genymotionvbox86p']

How could I compare that each item in the array matches the hashes value in the same order

So far I have

array.each do |value|
  hash.each do |k, v|
    expect(v).to eq(value), "expected #{k} to equal #{v}, instead got #{value}"
  end
end

This is failing as I get

expected av to equal av, instead got i (RSpec::Expectations::ExpectationNotMetError)

I'm not quite there yet and imagine that a loop within a loop is not the best thing to do either?

I would like to know how to efficiently approach this.

Upvotes: 0

Views: 89

Answers (3)

Gagan Gami
Gagan Gami

Reputation: 10251

How could I compare that each item in the array matches the hashes value in the same order

how about this?

> array == hash.values
#=> true 
>  array = ["i", "Genymotionvbox86p", "av"] # change the order
> array == hash.values
#=> false 

Upvotes: 0

ndnenkov
ndnenkov

Reputation: 36100

The reason this fails is because you compare every array value with every hash value. To solve this, you can take advantage of the fact that two arrays arrays are equal if all their values in order are equal:

expect(array).to eq hash.values

Upvotes: 5

Mladen Jablanović
Mladen Jablanović

Reputation: 44080

If you would really want to compare item-by-item, you rightfully noticed that a loop within a loop is not the way to go. You need a single loop to iterate both structures.

For that, you can, for example, use zip, to combine hash and array:

hash.zip(array).each do |(hash_key, hash_value), array_item|
  expect(hash_value).to eq array_item
end

or you can resort to using an index:

hash.each_with_index do |(k, v), i|
  expect(v).to eq array[i]
end

Upvotes: 1

Related Questions