Ответ 1
hash_object = objects.each_with_object({}) do |obj, hash|
hash[obj.object_id] = obj
end
[1, 2, 3, 4, 5].map { |index| hash_object[index] }
#=> array of objects in id order
Я считаю, что время выполнения будет O (n)
У меня есть массив идентификаторов
a1 = [1, 2, 3, 4, 5]
и у меня есть еще один массив объектов с идентификаторами в случайном порядке
a2 = [(obj_with_id_5), (obj_with_id_2), (obj_with_id_1), (obj_with_id_3), (obj_with_id_4)]
Теперь мне нужно отсортировать a2 в соответствии с порядком идентификаторов в a1. Итак, теперь a2 должен стать:
[(obj_with_id_1), (id_2), (id_3), (id_4), (id_5)]
a1 может быть [3, 2, 5, 4, 1] или в любом порядке, но a2 должен соответствовать порядку идентификаторов в a1.
Мне нравится следующее:
a1.each_with_index do |id, idx|
found_idx = a1.find_index { |c| c.id == id }
replace_elem = a2[found_idx]
a2[found_idx] = a2[idx]
a2[idx] = replace_elem
end
Но это все равно может занять время O (n ^ 2), если порядок элементов a2 точно обрат на a1. Может кто-нибудь, пожалуйста, скажите мне наиболее эффективный способ сортировки a2?
hash_object = objects.each_with_object({}) do |obj, hash|
hash[obj.object_id] = obj
end
[1, 2, 3, 4, 5].map { |index| hash_object[index] }
#=> array of objects in id order
Я считаю, что время выполнения будет O (n)
Я удивлюсь, если что-то намного быстрее, чем очевидный путь:
a2.sort_by{|x| a1.index x.id}
Мне нравится принятый ответ, но в ActiveSupport есть index_by, который упрощает создание начального хэша. См. Самый чистый способ создания хэша из массива
Фактически вы можете сделать это в одной строке, так как Enumerable также поддерживает index_by:
a2.index_by(&:id).values_at(*a1)
Вдохновленный Eric Woodruff Отвечать, я придумал следующее решение для ванили Ruby:
a2.group_by(&:object_id).values_at(*a1).flatten(1)
Документация по методу: