按计算元素排序

时间:2014-04-29 12:04:29

标签: ruby sorting collections

我有一个集合:

programmers = [
  {:name => "Martin", :speed => 2.0, :daily_wage => 2000},
  {:name => "Jarda", :speed => 1.0, :daily_wage => 1300},
  {:name => "Lukas", :speed => 0.5, :daily_wage => 900},
  {:name => "Pepa", :speed => 1.7, :daily_wage => 2200},
  {:name => "Kamil", :speed => 0.4, :daily_wage => 1800},
  {:name => "Honza", :speed => 1.2, :daily_wage => 1500},
  {:name => "Filip", :speed => 1.1, :daily_wage => 1000}
]

我想计算他们的质量

quality = (pro[:daily_wage] / pro[:speed])
sorted << [pro[:name], pro[:speed], pro[:daily_wage], quality]

按质量排序

sorted.sort_by { |a| a[3] }

我的技术不起作用,你能否给我一些重新设计这个集合的提示,以便在sorted上进行进一步的迭代?

2 个答案:

答案 0 :(得分:2)

这是我做的方式。首先,将计算放在lambda中:

quality = ->(pro) {pro[:daily_wage] / pro[:speed]}

然后你可以简洁地对集合进行排序:

programmers.sort_by &quality

这样您就不需要创建仅用于排序的中间数据结构。

但是,如果你想要永久保留质量度量,你可以为每个元素调用lambda,添加一个新的键/值对,然后对其进行排序:

programmers.each{|p| p[:quality] = quality[p]}.sort_by{|p| p[:quality]}

注意使用方括号调用lambda,这只是quality.call(p)

的简写

答案 1 :(得分:1)

编辑:我最初建议创建一个新的键/值对并同时进行排序:

programmers.sort_by { |h| h[:quality] = (h[:daily_wage]/h[:speed]).round(0) }

当我这样做时,我没有考虑到这将需要为sort_by完成的每个成对比较的两个元素计算块中的表达式。感谢@Mark指出这一点。 (请参阅他的回答评论。)因此,我已经开始以更直接的方式进行替换并按顺序排序:

arr = programmers.each {|h| h[:quality] = (h[:daily_wage]/h[:speed]).round(0)}
arr.sort_by {|h| h[:quality]}
  #=> [{:name=>"Filip",  :speed=>1.1, :daily_wage=>1000, :quality=> 909},
  #    {:name=>"Martin", :speed=>2.0, :daily_wage=>2000, :quality=>1000},
  #    {:name=>"Honza",  :speed=>1.2, :daily_wage=>1500, :quality=>1250},
  #    {:name=>"Pepa",   :speed=>1.7, :daily_wage=>2200, :quality=>1294},
  #    {:name=>"Jarda",  :speed=>1.0, :daily_wage=>1300, :quality=>1300},
  #    {:name=>"Lukas",  :speed=>0.5, :daily_wage=> 900, :quality=>1800},
  #    {:name=>"Kamil",  :speed=>0.4, :daily_wage=>1800, :quality=>4500}]