ruby - tipos - Ordenar una matriz según los elementos de otra matriz
propiedades de las matrices pdf (4)
Inspirado por la Respuesta de Eric Woodruff , se me ocurrió la siguiente solución Vanilla Ruby:
a2.group_by(&:object_id).values_at(*a1).flatten(1)
Documentación de método:
Tengo una serie de identificadores
a1 = [1, 2, 3, 4, 5]
y tengo otra matriz de objetos con identificadores en orden aleatorio
a2 = [(obj_with_id_5), (obj_with_id_2), (obj_with_id_1), (obj_with_id_3), (obj_with_id_4)]
Ahora necesito ordenar a2 de acuerdo con el orden de los identificadores en a1. Entonces a2 ahora debería convertirse en:
[(obj_with_id_1), (id_2), (id_3), (id_4), (id_5)]
a1 podría ser [3, 2, 5, 4, 1] o en cualquier orden, pero a2 debería corresponderse con el orden de los identificadores en a1.
Me gusta esto
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
Pero esto aún podría pasar a un tiempo O (n ^ 2) si el orden de los elementos de a2 es exactamente inverso a a1. ¿Puede alguien decirme la forma más eficiente de ordenar a2?
Me gusta la respuesta aceptada, pero en ActiveSupport hay index_by que hace que crear el hash inicial sea aún más fácil. Vea la forma más limpia de crear un hash desde una matriz
De hecho, puede hacer esto en una línea, ya que Enumerable también es compatible con index_by:
a2.index_by(&:id).values_at(*a1)
Me sorprendería si algo es mucho más rápido que la forma obvia:
a2.sort_by{|x| a1.index x.id}
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''s order
Creo que el tiempo de ejecución será O (n)