1

I have an array (array1) of hashes that looks like this :

array1 = [
           {:ID=>"1", :value=>"abc"},
           {:ID=>"2", :value=>"def"}
         ]

I can loop over each hash and check each hash value manually:

array1.each do |h|
  if h.has_value?("def")
    #do something
  end
end

Is there a way to check if the hash value "abc" exists within a hash inside the array without having to iterate over the array?

Artjom B.
  • 61,146
  • 24
  • 125
  • 222
danynl
  • 279
  • 1
  • 4
  • 18

4 Answers4

2

find method is the most concise way with an array.

array1.find { |item| item[:value] == 'abc' }

Anyway, if you can start directly with an hash is better but if you have to switch to an hash from an array to have the O(1) lookup, it will probably be slower anyway.

Ursus
  • 29,643
  • 3
  • 33
  • 50
2

use any? instead of each, it breaks in early stage if found, best case O(1) and worst case O(n)

word = "def"
is_present = array1.any? { |h| h.has_value?(word) }

is_present is true if word is found in hash otherwise false

aqfaridi
  • 719
  • 7
  • 11
1

One way or another, you can't avoid iterating over the array. Here's one way.

array1.flat_map(&:values).include?("def")
  #=> true

Note

array1.flat_map(&:values)
  #=> ["1", "abc", "2", "def"]
Cary Swoveland
  • 106,649
  • 6
  • 63
  • 100
0

You obviously have to iterate at least once over the elements of your array.

If you do this often, you should use another data format:

array1 = [
  { ID: '1', value: 'abc' },
  { ID: '2', value: 'def' },
  { ID: '3', value: 'abc' }
]

lookup_table = array1.each_with_object(Hash.new { |h, k| h[k] = [] }) do |hash, table|
  table[hash[:value]] << hash[:ID]
end

p lookup_table
# {"abc"=>["1", "3"], "def"=>["2"]}
p lookup_table['abc']
# ["1", "3"]

As a bonus, it gives you all the IDs for which this value is found, and it gives it fast.

If you just want to know if there's a value somewhere in your hashes, you could use a Set:

require 'set'
all_values = Set.new(array1.map{|h| h[:value]})
p all_values.include? 'abc'
# true
p all_values.include? 'xyz'
# false

Again, the lookup will be much faster than with an array of hashes.

Eric Duminil
  • 52,989
  • 9
  • 71
  • 124