对如何在ruby中对对象数组进行排序感到困惑

时间:2014-08-06 00:58:34

标签: ruby arrays sorting

我对红宝石比较新。我有一个名为claims的数组。 claims数组中的每个元素都是一个声明。如果我做claims[0].houses,我会得到一系列房屋。有两件事我很困惑。

第一种是当我在控制台中输入claims[0]时,我实际上并没有看到房产,但是当我claims[0].houses时,我看到了我的一系列房屋。房屋是索赔对象的财产吗?

我的第二个问题是关于我的claims数组的排序。每个house都有一个价格属性。所以我的数据结构如下所示:

Claim[0]  Claim[1]  Claim[2]

house[0]: house[0]: house[2]
price: 20 price: 24 price: 11

house[1]: house[1]: house[2]:
price: 17 price 30  price: 28

我想要做的是按最便宜的价格房子排序我的索赔,因此claims的第0个索引应该有houses数组和最便宜的房子。 claims数组的第一个索引应该有houses数组,第二个最便宜的房子就像这样:

Claim[0]  Claim[1]  Claim[2]

house[0]: house[0]: house[2]
price: 11 price: 20 price: 24

house[1]: house[1]: house[2]:
price: 28 price 17  price: 30

为了解释我如何得到上面的结果,我发现houses中的Claim[2]数组在11处的房子最便宜。所以进入Claim[0]。然后我发现剩余的未分类的houses,原来在Claim[0]的那个最便宜的房子在17,所以它进入了Claim[1]

我无法弄清楚如何在ruby中做到这一点。

我尝试了很多东西,包括:

claims.sort!{|a,b| a.price.min <=> b.price.min}

但我收到的错误是undefined method price for #<Claim:0x0000010>

然后我尝试了

claims.sort!{|a, b| a.house.price.min <=> a.house.price.min}

我再次收到undefined method price for #<Array:0x00000e7b>

的错误消息

关于如何做到这一点的任何想法?

2 个答案:

答案 0 :(得分:3)

你可以像这样紧凑地做:

claims.sort_by! { |claim| claim.houses.map{|h| h.price}.min}

起初这可能看起来效率低下,但实际上并不是因为sort_by is implemented的方式。


您也可以分两步完成 - 这种方式可能会慢一些,具体取决于您的计划细节。

首先,按价格对每一组房屋进行排序:

claims.each do |claim|
  claim.houses.sort_by! { |house| house.price }
end

我们现在知道每个索赔中的第一个房子是该索赔最便宜的。然后我会对索赔进行排序:

claims.sort_by! { |claim| claim.houses.first.price }

查看documentation for sort_by!


我还没有对这些问题进行过测试,如果您遇到任何问题或有任何其他问题,请随时发表评论

答案 1 :(得分:0)

根据你的例子,我做了一个演示来排序。

claims = [
  {houses: [{price: 20},{price: 17}]},
  {houses: [{price: 24},{price: 30}]},
  {houses: [{price: 11},{price: 28}]} ]
claims.sort{|x,y| x[:houses].map{|h| h[:price]}.min <=> y[:houses].map{|h| h[:price]}.min}
=> [{:houses=>[{:price=>11}, {:price=>28}]},
    {:houses=>[{:price=>20}, {:price=>17}]},
    {:houses=>[{:price=>24}, {:price=>30}]}]

结果就是你想要的。

但是,因为我使用数组和哈希而不是对象,您可以使用x.houses代替x[:houses],使用h.price代替h[:price]

如果你在Claim对象中添加min_price方法,那就更好了。

Class Claim
  def min_price
    houses.map{|h| h.price}.min
  end
end

claims.sort{|x,y| x.min_price <=> y.min_price}