Ruby 如何在避免被零除的同时按比率排序?

Ruby 如何在避免被零除的同时按比率排序?,ruby,algorithm,sorting,Ruby,Algorithm,Sorting,考虑一个班级团队,班级变量为“赢”和“输”。我希望按照赢:输比率对一系列团队进行排序,以便: 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

考虑一个班级团队,班级变量为“赢”和“输”。我希望按照赢:输比率对一系列团队进行排序,以便:

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)

在团队类中,可以这样使用:

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

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

每个团队都有一个获胜百分比,并根据这个百分比排序。在每个获胜百分比中,您应该按照所玩游戏的总数进行排序,确保根据团队的总获胜百分比小于或大于50%来决定总游戏是好是坏。

与其定义一个方法来使用
排序依据
,不如覆盖
,以便它处理比较,然后你可以避免创建一个数字,而是做如下的事情

(@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
def <=>(other)
  if losses == 0
    -1
  elsif other.losses == 0
    1
  else
    # do ratio logic here
  end
end
def(其他)
如果损失==0
-1
elsif other.Loss==0
1.
其他的
#在这里做比率逻辑
结束
结束

基于以上评论,我同意使用一个可排序的编号就可以了。也许是这样的:

def win_loss_ranking
  (@wins *2 ) - (@losses * 2) + (@wins + @losses)
end
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]

这将为您提供一个考虑到所玩游戏以及胜负的数字。因此,在5:5和3:3的情况下,5:5的胜负排名为10,3:3的团队排名为6。

我不会说Ruby,但Python方法会给出您想要的结果,它会使用一个元组作为键(在装饰排序的“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\u by
方法在某处浮动。

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

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

teams.sort!{|a, b| a.difference <=> b.difference}
班级团队
def差异@胜负结束
结束
团队,排序!{| a,b | a.差b.差}
添加的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"]
def等级(wl)
w、 l=wl.split(/:/).map(&:to_f)
[w/(w+l>0?-(w+l):0),-w,l]
结束
>排序{a,b |秩(a)秩(b)}
["5:0", "3:0", "1:0", "3:1", "5:5", "3:3", "1:3", "0:1", "0:3", "0:5"]
然后,如果您想将其转换为oo格式,可以是:

def win_loss_ranking
  (@wins *2 ) - (@losses * 2) + (@wins + @losses)
end
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]
Wl类
def初始化(赢/输)
@wl=赢与输
结束
def wl()
@wl
结束
def秩()
w、 l=@wl.split(/:/).map(&:to\u f)
[w/(w+l>0?-(w+l):0),-w,l]
结束
def至美国
@wl
结束
def检查
@wl
结束
def(其他)
排名
结束
结束
>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.分类
[5:0, 3:0, 1:0, 3:1, 5:5, 3:3, 1:3, 0:1, 0:3, 0:5]

我认为逻辑非常复杂,不想指定一个数字(比率),而是在赢/亏数据结构上定义排序。我不建议尝试将赢/亏比率转换为可以排序的数字。您不会试图以这种方式对字符串进行排序,对吗?
+1
+2
有任何逻辑吗?仅仅因为它们是最简单的数字就行了?它们必须是非零才能进行排序
5:0>0:5
,不同的数字才能进行排序
5:5>3:3
,但除此之外,我随意选择了它们(以及
3
)。确保你有足够的注释,以免有人在神秘的1背后度过不眠之夜,2和3:)是的,理想情况下,你可以在一个更大的数据集上测试它,并选择一些对你来说很好的值。对不起,我认为这是可行的,但事实并非如此。考虑1:0和7:1的情况,评估为2和4.4。因此,这不会按比率排序。我会更新原始的订单规格。如果你必须把它归结为一个单一的数字进行排名,这可能是最好的方法。但是我们想要1:0>99:1吗?根据问题,是的。根据我生疏的代数,那就是
3*@wins-@loss
;(5胜5负)超过(3胜0负)。事实上,.
wl.sort_by{win,loss{win.to_f/(win+loss>0?win+loss:0),win,-loss]}
是红宝石的等价物()。你需要第三项吗?如果两个队有相同的获胜百分比和相同的获胜次数,他们必然有相同的失败次数。@chepner:不,他们没有。考虑(0,3)和(0,5),它们都具有相同的获胜百分比(0%)和相同的获胜数(0),但它们有不同的损失数。@ DSM:噢,当然。这就是我星期五下午尝试使用大脑的原因。考虑1:0和7:1,当排序不会按比例排序。你期望的结果是什么?你不想让它排序,或者以某种方式排序?按“比率”排序,例如:5:0>3:0>1:0>3:1>5:5>3:3>1:3>0:1>0:3>0:5。按差异排序时,3:1>1:0。我应该在原始示例中包括1:0和0:1。