2016-09-18 3 views
0

Я пытаюсь сравнить выбранный массив animal_id с объектом «animal_id» в массиве owner_to_animals, чтобы у меня был список только соответствующих прав владельца. Я попытался выполнить итерацию через хэш, а затем выберите объект animal_id, который соответствует в массиве animal_id, но он выдает animal_id = 20, который не является частью массива animal_id.Сравнение хеша массивов с массивом, чтобы найти сходство

animal_id = [23, 53, 63] 
owners_to_animals = [ 
    { "owner_id" => 73, "animal_id" => 53 }, 
    { "owner_id" => 73, "animal_id" => 23 }, 
    { "owner_id" => 73, "animal_id" => 63 }, 
    { "owner_id" => 73, "animal_id" => 20 }, 
    { "owner_id" => 83, "animal_id" => 23 }, 
    { "owner_id" => 83, "animal_id" => 63 } 
] 

owners_to_animals.each do |x| 
    # puts x 
    # x.each do |y| 
    for i in animal_id do 
    # puts i 
    if x.select { |a| a["animal_id"] == i } 
     puts x 
    else 
     puts "no" 
    end 
    end 

    # end 

end 

Я запутался, почему х возвращается:

{"owner_id"=>73, "animal_id"=>53} 
{"owner_id"=>73, "animal_id"=>53} 
{"owner_id"=>73, "animal_id"=>53} 
{"owner_id"=>73, "animal_id"=>23} 
{"owner_id"=>73, "animal_id"=>23} 
{"owner_id"=>73, "animal_id"=>23} 
{"owner_id"=>73, "animal_id"=>63} 
{"owner_id"=>73, "animal_id"=>63} 
{"owner_id"=>73, "animal_id"=>63} 
{"owner_id"=>73, "animal_id"=>20} 
{"owner_id"=>73, "animal_id"=>20} 
{"owner_id"=>73, "animal_id"=>20} 
{"owner_id"=>83, "animal_id"=>23} 
{"owner_id"=>83, "animal_id"=>23} 
{"owner_id"=>83, "animal_id"=>23} 
{"owner_id"=>83, "animal_id"=>63} 
{"owner_id"=>83, "animal_id"=>63} 
{"owner_id"=>83, "animal_id"=>63} 
+1

Я редактировал свой код для форматирования, а также 'owners_to_animals' явного массива, так как исходный код был немного запутанным , –

+0

'owner_to_animals.select {| o_a | animal_id.include? o_a ['animal_id']} ' – mudasobwa

+0

@mudasobwa Вот именно ответ, который я опубликовал за 3 часа до вашего комментария;) –

ответ

3

select возвращает пустой массив, если ничего не соответствует, что в Ruby, является «truthy» значение, так else ветвь вашего код никогда не выполняется.

if [] 
    puts "true" 
else 
    puts "false" 
end 
# Outputs "true" 

То, что вы хотите достичь может быть сделана в одной строке:

puts owners_to_animals.select { |x| animal_id.include?(x["animal_id"]) } 
# Output: 
{"owner_id"=>73, "animal_id"=>53} 
{"owner_id"=>73, "animal_id"=>23} 
{"owner_id"=>73, "animal_id"=>63} 
{"owner_id"=>83, "animal_id"=>23} 
{"owner_id"=>83, "animal_id"=>63} 
+2

В подобных ситуациях, когда массивы' animal_id' и/или 'owner_to_animals' являются большими, может быть целесообразным сначала преобразовать первое в набор: 'require 'set'; animal_id_set = animal_id.to_set; owner_to_animals.select {| x | animal_id_set.include? (x ["animal_id"])} '. Установить поиск очень быстро по сравнению с переходом через массив, который выполняется для каждого элемента (хэша) 'owner_to_animals'. –

+0

@CarySwoveland Не будет ли конверсия, чтобы установить стоимость разницы? – ZenMaster

+0

Это сравнительно небольшая разовая стоимость (в основном, превращение массива в хэш с элементами массива в виде ключей и «nil» в качестве значений для поиска O (1)), в отличие от O (n) поиска каждый раз, что может быть проблематичным, если 'animal_id' велико. –

 Смежные вопросы

  • Нет связанных вопросов^_^