2

考虑一个类 Team,类变量为“wins”和“losses”。我希望按胜负比对一组团队进行排序,例如:

5:0 > 3:0 > 1:0 > 3:1 > 5:5 > 3:3 > 1:3 > 0:1 > 0:3 > 0:5

我已经有一个我不满意的(部分)破解的解决方案,我想知道是否有更清洁/更优雅/更简单的方法来解决这个问题。

def ratio
    if @losses == 0 then 
        return 1000000+@wins
    end
    if @wins == 0 then
        return 0-@losses
    end
    return @wins/@losses
end

(这不能解决 5:5 > 3:3)

这将在 Team 类中,可以像这样使用:

teams.sort! { |a, b| b.ratio <=> a.ratio }

解决这个问题的最简单方法是什么?(解决方案不一定是 Ruby,我对 OO 的任何东西都很满意)

4

7 回答 7

3

我不会说 Ruby,但是可以提供所需结果的 Python 方法将使用元组作为键(在 decorate-sort-undecorate “Schwartzian transform” 成语中。)

例如,您可以按获胜分数、获胜次数和(负)失败次数进行排名,这将给出您想要的排序:

>>> wl = [[3, 0], [3, 1], [0, 5], [3, 3], [0, 3], [5, 5], [1, 3], [5, 0]]
>>> 
>>> def rank(wl):
...     win, loss = wl
...     return (1.0*win/(win+loss) if win+loss > 0 else 0), win, -loss
... 
>>> sorted(wl, key=rank)
[[0, 5], [0, 3], [1, 3], [3, 3], [5, 5], [3, 1], [3, 0], [5, 0]]
>>> sorted(wl, key=rank)[::-1]
[[5, 0], [3, 0], [3, 1], [5, 5], [3, 3], [1, 3], [0, 3], [0, 5]]

不幸的是,我不知道 Ruby 等价物是什么,但我认为有一种sort_by方法在某处浮动。

于 2013-01-25T21:23:59.690 回答
2

与其定义一个使用 with 的方法sort_by,不如重写<=>它来处理比较,然后你可以避免创建一个数字,而是做类似的事情

def <=>(other)
  if losses == 0
    -1
  elsif other.losses == 0
    1
  else
    # do ratio logic here
  end
end
于 2013-01-25T21:08:20.030 回答
1

为每支球队设定一个胜率并对其进行排序。在每个胜率中,您应该按总比赛场次进行排序,确保根据球队的总胜率低于或高于 50% 来确定总场数的好坏。

于 2013-01-25T21:04:11.210 回答
1
(@wins * 3 + 1) / (@losses * 3 + 2)

5:0 8.00
3:0 5.00
3:1 2.00
5:5 0.94
3:3 0.91
1:3 0.36
0:3 0.09
0:5 0.06
于 2013-01-25T21:07:41.150 回答
0

根据上面的评论,我同意一个可排序的数字会很好用。也许是这样的:

def win_loss_ranking
  (@wins *2 ) - (@losses * 2) + (@wins + @losses)
end

这为您提供了一个数字,该数字考虑了所玩的游戏以及输赢。因此,在您有 5:5 和 3:3 的情况下,5:5 的 win_loss_ranking 为 10,而 3:3 的团队为 6。

于 2013-01-25T21:10:11.320 回答
0

比率(在与您的目的相关的意义上)将随着差异单调增加。为什么不使用差异来实现它?

class Team
  def difference; @wins - @losses end
end

teams.sort!{|a, b| a.difference <=> b.difference}
于 2013-01-25T21:56:28.843 回答
0

添加DSM 的 Python 版本的 Ruby 版本

鉴于:

> a=["0:1", "5:0", "3:3", "0:3", "1:3", "3:0", "1:0", "0:5", "5:5", "3:1"]

你可以做:

def rank(wl)
    w, l = wl.split(/:/).map(&:to_f)
    [w/(w+l > 0 ? -(w+l) : 0), -w, l]
    end
> a.sort { |a,b| rank(a)<=>rank(b) }
["5:0", "3:0", "1:0", "3:1", "5:5", "3:3", "1:3", "0:1", "0:3", "0:5"]

然后,如果您想以 oo 格式使用它,可能类似于:

class Wl 
   def initialize(win_loss)
       @wl=win_loss
   end
   def wl()
      @wl
   end 
   def rank()
      w, l = @wl.split(/:/).map(&:to_f)
      [w/(w+l > 0 ? -(w+l) : 0), -w, l]
   end
   def to_s
       @wl
   end
   def inspect
       @wl 
   end 
   def <=>(other)
      rank <=> other.rank
   end 
end

> b=a.map{ |e| Wl.new(e) }
[0:1, 5:0, 3:3, 0:3, 1:3, 3:0, 1:0, 0:5, 5:5, 3:1]
> b.sort
[5:0, 3:0, 1:0, 3:1, 5:5, 3:3, 1:3, 0:1, 0:3, 0:5]
于 2017-07-14T01:34:48.280 回答