这种方法涉及比采用sort
或sort_by
,那些多个步骤,但对于更大的阵列可能更快,因为没有排序 - 这是相对昂贵 - 参与。
代码
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
例
首先,让我们创建的
实例的数组像这样:
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">]
然后
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">]
说明
对于instances
作为示例中定义,首先在所希望的顺序创建大小的数组:
names = @sizes_sort_order & (instances.map { |s| s.name })
#=> ["XS/S", "M", "M/L"]
重要:该文档对于Array#&状态,“订单从原始数组中保留。”。
现在,我们可以创建所需的重新排序,而无需排序,方法是创建一个具有键值的实例的大小和值的散列,然后使用Hash#values_at以所需顺序提取实例。
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">]
最后的操作涉及以下两个步骤。
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">]
看['可枚举#sort_by'(http://ruby-doc.org/core-2.2.0/Enumerable.html#method-i-sort_by) –