This approach involves more steps than ones that employ sort or sort_by, but for larger arrays it may be faster, as no sorting--which is relatively expensive--is involved.
Code
def reorder_by_size(instances, size_order)
instances.each_with_object({}) { |inst, h| h.update(inst.name=>inst) }.
values_at(*(size_order & (instances.map { |s| s.name })))
end
Example
First let's create an array of instances of
class Sizes
attr_reader :name
def initialize(id, name)
@id = id
@name = name
end
end
like so:
instances = [Sizes.new(5,'M'), Sizes.new(6,'M/L'), Sizes.new(7, 'XS/S')]
#=> [#<Sizes:0x007fa66a955ac0 @id=5, @name="M">,
# #<Sizes:0x007fa66a955a70 @id=6, @name="M/L">,
# #<Sizes:0x007fa66a955a20 @id=7, @name="XS/S">]
Then
reorder_by_size(instances, @sizes_sort_order)
#=> [#<Sizes:0x007fa66a01dfc0 @id=7, @name="XS/S">,
# #<Sizes:0x007fa66a86fdb8 @id=5, @name="M">,
# #<Sizes:0x007fa66a8404f0 @id=6, @name="M/L">]
Explanation
For instances as defined for the example, first create an array of sizes in the desired order:
names = @sizes_sort_order & (instances.map { |s| s.name })
#=> ["XS/S", "M", "M/L"]
Important: the doc for Array#& states, "The order is preserved from the original array.".
Now we can create the desired reordering without sorting, by creating a hash with keys the sizes and values the instances, then use Hash#values_at to extract the instances in the desired order.
instances.each_with_object({}) { |inst, h|
h.update(inst.name=>inst) }.values_at(*names)
#=> [#<Sizes:0x007fa66a01dfc0 @id=7, @name="XS/S">,
# #<Sizes:0x007fa66a86fdb8 @id=5, @name="M">,
# #<Sizes:0x007fa66a8404f0 @id=6, @name="M/L">]
The last operation involves the following two steps.
h = instances.each_with_object({}) { |inst, h| h.update(inst.name=>inst) }
#=> {"M" => #<Sizes:0x007fa66a955ac0 @id=5, @name="M">,
# "M/L" => #<Sizes:0x007fa66a955a70 @id=6, @name="M/L">,
# "XS/S" => #<Sizes:0x007fa66a955a20 @id=7, @name="XS/S">}
h.values_at(*names)
#=> h.values_at(*["XS/S", "M", "M/L"])
#=> h.values_at("XS/S", "M", "M/L")
#=> [#<Sizes:0x007fa66a955a20 @id=7, @name="XS/S">,
# #<Sizes:0x007fa66a955ac0 @id=5, @name="M">,
# #<Sizes:0x007fa66a955a70 @id=6, @name="M/L">]
Enumerable#sort_by