使用自定义顺序对数组进行排序

Posted

技术标签:

【中文标题】使用自定义顺序对数组进行排序【英文标题】:Sort array with custom order 【发布时间】:2014-04-19 15:16:25 【问题描述】:

我有一个 ids order 数组

order = [5,2,8,6]

和另一个哈希数组

 [id: 2,name: name2,id: 5,name: name5, id: 6,name: name6, id: 8,name: name8]   

我希望它排序为

[id: 5,name: name5,id: 2,name: name2, id: 8,name: name8, id: 6,name: name6] 

实现这一点的最佳方法是什么?我可以通过迭代两者并将其推送到新数组但寻找更好的解决方案来实现这一点。

【问题讨论】:

【参考方案1】:

试试这个

arr = [  
         :id=>2, :name=>"name2", :id=>5, :name=>"name5", 
         :id=>6, :name=>"name6", :id=>8, :name=>"name8"
      ]

order = [5,2,8,6]

arr.sort_by  |a| order.index(a[:id]) 
# => [:id=>5, :name=>"name5", :id=>2, :name=>"name2", 
#:id=>8, :name=>"name8", :id=>6, :name=>"name6"] 

【讨论】:

【参考方案2】:

Enumerable#in_order_of (Rails 7+)


Rails 7开始,有一个新方法Enumerable#in_order_of。

来自官方 Rails 文档的引用:

in_order_of(key, series)

根据原始可枚举对象的key,返回一个新的Array,其中的顺序已设置为series 中提供的顺序。

[ Person.find(5), Person.find(3), Person.find(1) ].in_order_of(:id, [ 1, 5, 3 ])
=> [ Person.find(1), Person.find(5), Person.find(3) ]

如果series 包含在Enumerable 中没有对应元素的键,则这些键将被忽略。如果Enumerable 包含series 中未命名的其他元素,则这些元素不会包含在结果中。


在散列的情况下它并不完美,但您可以考虑如下:

require 'ostruct'

items = [ id: 2, name: 'name2' ,  id: 5, name: 'name5' ,  id: 6, name: 'name6' ,  id: 8, name: 'name8' ]

items.map(&OpenStruct.method(:new)).in_order_of(:id, [5,2,8,6]).map(&:to_h)
# => [:id=>5, :name=>"name5", :id=>2, :name=>"name2", :id=>8, :name=>"name8", :id=>6, :name=>"name6"]

来源:

官方文档 - Enumerable#in_order_of. 公关 - Enumerable#in_order_of #41333. Rails 7 adds Enumerable#in_order_of。

【讨论】:

以上是关于使用自定义顺序对数组进行排序的主要内容,如果未能解决你的问题,请参考以下文章

按自定义字典顺序对字符串进行排序

如何按自定义顺序对 JavaScript 中的数组进行排序? [复制]

在 Eloquent 中按自定义顺序对集合进行排序 [重复]

如何根据自定义所需顺序对包含列表的数组列表进行排序

PHP按自定义顺序对工作日和月份-年份数组进行排序

使用自定义排序顺序对对象的 ArrayList 进行排序