如何通过确定特定属性的优先级来对数组进行排序

时间:2014-01-18 11:50:41

标签: ruby

所以我从ActiveRecord获取记录,我想做类似的事情:

VIP_LIST = ['John', 'Larry', 'Dan']

records = [
 { name: "Adam" },
 { name: "Larry" },
 { name: "John" },
 { name: "Eric" },
 { name: "Dan" }
]

# This is what I want to end up with:

sort_please(records, VIP_LIST)
  => [
   { name: "John" },
   { name: "Larry" },
   { name: "Dan" },
   { name: "Adam" },
   { name: "Eric" }
  ]

我怎样才能实现这个目标?

P.S。 VIP_LIST中的值可能甚至不在记录中

4 个答案:

答案 0 :(得分:3)

这不是一个聪明的单线,但它的工作原理:

VIP_LIST = ['John', 'Larry', 'Dan', 'Fred']

records = [
 { name: "Adam" },
 { name: "Larry" },
 { name: "John" },
 { name: "Eric" },
 { name: "Dan" }
]

  sorted = records.sort_by do |record|
    name = record[:name]
    if VIP_LIST.include?(name)
      VIP_LIST.index(name)
    else
      records.index(record) + VIP_LIST.length
    end
  end

  p sorted # => [{:name=>"John"}, {:name=>"Larry"}, {:name=>"Dan"}, {:name=>"Adam"}, {:name=>"Eric"}]

答案 1 :(得分:1)

这一个?

new_arr = []
VIP_LIST.each do |v|
  new_arr << records.select {|r| r[:name] == v } unless nil?
end
new_arr.flatten!
new_arr = new_arr + (records - new_arr)

答案 2 :(得分:1)

试试这个:

records.sort_by do |x|
  [VIP_LIST.index(x[:name]) || VIP_LIST.length, records.index(x)]
end

# => [{:name=>"John"}, {:name=>"Larry"}, {:name=>"Dan"}, {:name=>"Adam"}, {:name=>"Eric"}]

答案 3 :(得分:0)

我认为这既清晰又简洁:

vip = records.select{ |hash| VIP_LIST.include? hash[:name] }
vip = vip.sort_by{|x| VIP_LIST.find_index(x[:name])} #reorder vip array
sorted_records = (vip + records).uniq