這種方法涉及比採用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) –