Это лучший способ получить общие элементы из хэша массивов? - PullRequest
4 голосов
/ 25 марта 2010

Я пытаюсь получить общий элемент из группы массивов в Ruby. Обычно вы можете использовать Оператор & для сравнения двух массивов, который возвращает элементы, которые присутствуют или являются общими в обоих массивах. Это все хорошо, за исключением случаев, когда вы пытаетесь получить общие элементы из более чем двух массивов. Однако я хочу получить общие элементы из неизвестного, динамического числа массивов , которые хранятся в хэше.

Мне пришлось прибегнуть к использованию метода eval () в ruby, который выполняет строку как реальный код. Вот функция, которую я написал:

  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

Это работает и отлично, но мне интересно ... eval, правда? Это лучший способ сделать это? Существуют ли какие-либо другие способы сделать это (кроме, конечно, рекурсивной функции). Если у кого-то есть предложения, я весь слух.

В противном случае, не стесняйтесь использовать этот код, если вам нужно извлечь общий элемент или элемент из группы или хэша массивов, этот код также можно легко адаптировать для поиска в массиве массивов.

Ответы [ 3 ]

16 голосов
/ 25 марта 2010

Вот сила inject! ;)

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

Как упоминал Джордан, если в вашей версии Ruby отсутствует поддержка & -notation, просто используйте

inject{|acc,elem| acc & elem}
0 голосов
/ 25 марта 2010

Почему бы не сделать это:

def get_common_elements_for_hash_of_arrays(hash)
    ret = nil
    hash.each do |key, array|
        if ret.nil? then
            ret = array
        else
            ret = array & ret
        end
    end
    ret = Array.new if ret.nil? # give back empty array if passed empty hash
    return ret
end
0 голосов
/ 25 марта 2010

Разве вы не можете просто сравнить первые два, взять результат и сравнить его со следующим и т. Д.? Кажется, это соответствует вашим критериям.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...