IDの配列があります
a1 = [1, 2, 3, 4, 5]
そして私はランダムな順序でIDを持つオブジェクトの別の配列を持っています
a2 = [(obj_with_id_5), (obj_with_id_2), (obj_with_id_1), (obj_with_id_3), (obj_with_id_4)]
次に、a1のIDの順序に従ってa2をソートする必要があります。したがって、a2は次のようになります。
[(obj_with_id_1), (id_2), (id_3), (id_4), (id_5)]
a1は[3、2、5、4、1]または任意の順序ですが、a2はa1のIDの順序に対応している必要があります。
私はこれが好きです:
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
ただし、a2の要素の順序がa1の順序と完全に逆の場合、これはO(n ^ 2)時間に実行される可能性があります。誰かが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's order
ランタイムはO(n)になると思います
明白な方法よりもはるかに速いものがあれば、私は驚きます:
a2.sort_by{|x| a1.index x.id}
私は受け入れられた答えが好きですが、ActiveSupportにはindex_byがあります。これにより、初期ハッシュの作成がさらに簡単になります。 配列からハッシュを作成する最も簡単な方法 を参照してください
Enumerableはindex_byもサポートしているため、実際には1行でこれを行うことができます。
a2.index_by(&:id).values_at(*a1)
Eric Woodruff's Answer に触発されて、私は次のバニラRubyソリューションを考え出しました:
a2.group_by(&:object_id).values_at(*a1).flatten(1)
メソッドのドキュメント: