Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is this the best way to grab common elements from a Hash of arrays?

Tags:

ruby

I'm trying to get a common element from a group of arrays in Ruby. Normally, you can use the & operator to compare two arrays, which returns elements that are present or common in both arrays. This is all good, except when you're trying to get common elements from more than two arrays. However, I want to get common elements from an unknown, dynamic number of arrays, which are stored in a hash.

I had to resort to using the eval() method in ruby, which executes a string as actual code. Here's the function I wrote:

  def get_common_elements_for_hash_of_arrays(hash) # get an array of common elements contained in a hash of arrays, for every array in the hash.
       # ["1","2","3"] & ["2","4","5"] & ["2","5","6"] # => ["2"]
       # eval("[\"1\",\"2\",\"3\"] & [\"2\",\"4\",\"5\"] & [\"2\",\"5\",\"6\"]") # => ["2"]
       eval_string_array = Array.new # an array to store strings of Arrays, ie: "[\"2\",\"5\",\"6\"]", which we will join with & to get all common elements
       hash.each do |key, array|
          eval_string_array << array.inspect 
       end
       eval_string = eval_string_array.join(" & ") # create eval string delimited with a & so we can get common values 
       return eval(eval_string)
  end

example_hash = {:item_0 => ["1","2","3"], :item_1 => ["2","4","5"], :item_2 => ["2","5","6"] }
puts  get_common_elements_for_hash_of_arrays(example_hash) # => 2

This works and is great, but I'm wondering...eval, really? Is this the best way to do it? Are there even any other ways to accomplish this(besides a recursive function, of course). If anyone has any suggestions, I'm all ears.

Otherwise, Feel free to use this code if you need to grab a common item or element from a group or hash of arrays, this code can also easily be adapted to search an array of arrays.

like image 593
dhulihan Avatar asked Mar 25 '10 18:03

dhulihan


1 Answers

Behold the power of inject! ;)

[[1,2,3],[1,3,5],[1,5,6]].inject(&:&)
=> [1]

As Jordan mentioned, if your version of Ruby lacks support for &-notation, just use

inject{|acc,elem| acc & elem}
like image 107
Mladen Jablanović Avatar answered Oct 26 '22 22:10

Mladen Jablanović