按类别名称对数组进行排序

时间:2015-01-08 16:39:05

标签: ruby arrays sorting

鉴于此数组a

a = [
    {id: 3, category_name: "Horror"},
    {id: 4, category_name: "Non-Fiction"},
    {id: 5, category_name: "LGBT"},
    {id: 6, category_name: "Romance"},
    {id: 7, category_name: "Romance"}
]

我想使用数组(索引)的顺序按类别名称对数组a中的对象进行排序,因为Ruby数组默认是有序数组:

categories_sorted = [
   "Romance",
   "LGBT",
   "Non-Fiction",
   "Horror"
]

因此排序算法会给我一个如下所示的数组:

result = [
    {id: 6, category_name: "Romance"},
    {id: 7, category_name: "Romance"},
    {id: 5, category_name: "LGBT"},
    {id: 4, category_name: "Non-Fiction"},
    {id: 3, category_name: "Horror"}
]

你能指出任何有效实现这一目标的方法吗? 数组“a”可以大到20个对象,排序的类别在我的场景中可以有多达30个类别。

3 个答案:

答案 0 :(得分:3)

执行以下操作: -

a = [
    {id: 3, category_name: "Horror"},
    {id: 4, category_name: "Non-Fiction"},
    {id: 5, category_name: "LGBT"},
    {id: 6, category_name: "Romance"},
    {id: 7, category_name: "Romance"}
]

categories_sorted = [
   "Romance",
   "LGBT",
   "Non-Fiction",
   "Horror"
]

p a.sort_by { |h| [categories_sorted.index(h[:category_name]), h[:id]] }
# >> [{:id=>6, :category_name=>"Romance"}, {:id=>7, :category_name=>"Romance"}, {:id=>5, :category_name=>"LGBT"}, {:id=>4, :category_name=>"Non-Fiction"}, {:id=>3, :category_name=>"Horror"}]

答案 1 :(得分:2)

值得编译排序索引列表以避免不断查找:

categories_sorted_index = Hash[
  categories_sorted.each_with_index.collect do |name, index|
    [ name, index ]
  end
]

a.sort_by do |entry|
  categories_sorted_index[entry[:category_name]] || 0
end

# =>
# {:id=>7, :category_name=>"Romance"}
# {:id=>6, :category_name=>"Romance"}
# {:id=>5, :category_name=>"LGBT"}
# {:id=>4, :category_name=>"Non-Fiction"}
# {:id=>3, :category_name=>"Horror"}

答案 2 :(得分:2)

以下是一种使用Enumerable#group_byHash#values_at而不是Enumerable#sort_by的方式:

a.group_by { |h| h[:category_name] }.values_at(*categories_sorted).flatten
  #=> [{:id=>6, :category_name=>"Romance"},
  #    {:id=>7, :category_name=>"Romance"},
  #    {:id=>5, :category_name=>"LGBT"},
  #    {:id=>4, :category_name=>"Non-Fiction"},
  #    {:id=>3, :category_name=>"Horror"}]