ruby为什么对以1和0为二进制的字母数字字符串进行排序?

问题描述

我有一个数组young = (input() == 'True') famous = (input() == 'True') if young=='True' and famous=='True': print('You must be rich!') else: print('There is always the lottery...') 。排序后,得到以下结果:

["Q10","Q100","Q1000","Q1000a","Q1001","Q98"]

由于这种行为,我不能正确地排序我的ActiveRecord对象。我有一个['Q100','Q1000','Q1000a','Q98','Q10','Q1001'].sort ["Q10","Q98"] 模型,其中有一个字段Question。我需要根据标签对它进行排序。因此,带有标签label的问题将是第一个,带有标签Q1的问题将是第一个,依此类推。我得到与上述数组示例所述的ActiveRecord相似的顺序。我正在使用postgresql作为数据库

现在我有3个问题。

  1. 为什么字母数字字符串排序会那样?
  2. 如何在不使用排序块的情况下实现所需的排序?
  3. 如何在ActiveRecord中实现这种排序?

解决方法

如果您的数组是

arr = ["Q10","Q100","Q1000","Q8","Q1001","Q98"]

你可以写

arr.sort_by { |s| s[/\d+/].to_i }
  #=> ["Q8","Q10","Q98","Q1001"]

如果

s = "Q1000"

然后

s[/\d+/].to_i
  #=> 1000

请参见Enumerable#sort_byString#[]

正则表达式/\d+/与包含一个或多个数字的s子字符串匹配。


如果数组是

arr = ["Q10b","Q10a","Q10c"]

你可以写

arr.sort_by { |s| [s[/\d+/].to_i,s[/\D+\z/]] }
  #=> ["Q10a","Q10b","Q10c","Q1001"] 

如果

s = "Q10b"

然后

[s[/\d+/].to_i,s[/\D+\z/]]
  #=> [10,"b"]

正则表达式/\D+\z/s的子字符串匹配,该子字符串在字符串的末尾(\z)包含一个或多个非数字。

请参阅Array#<=>,特别是第三段,以获取有关排序时如何对数组进行排序的说明。


如果数组是

arr = ["Q10b","P100","PQ10a","Q10c"]

你可以写

arr.sort_by { |s| [s[/\A\D+/],s[/\d+/].to_i,s[/\D+\z/]] }
  #=> ["P100","Q1001"]

如果

s = "PQ10a"

然后

[s[/\A\D+/],s[/\D+\z/]]
  #=> ["PQ",10,"a"]

正则表达式/\A\D+/s的子字符串匹配,该子字符串在字符串的开头(\A)包含一个或多个非数字。

,

这应该为您解决问题,在排序之前将其转换为数字。

['100','1000','98','10','1001'].map(&:to_i).sort

这个奇怪的map(&:to_i)map { |x| x.to_i }的简写

编辑:

您可以使用AR执行此操作。如果该列不包含伪装成字符串的数字,则会抛出错误。

Model.order("some_column::integer")

编辑II:

如果它也包含字符串,请尝试。

Model.order("cast(some_column as integer))"