我在 Ruby 中有一个数组,其值如下
xs = %w(2.0.0.1
2.0.0.6
2.0.1.10
2.0.1.5
2.0.0.8)
等等。我想对数组进行排序,最终结果应该是这样的:
ys = %w(2.0.0.1
2.0.0.6
2.0.0.8
2.0.1.5
2.0.1.10)
我曾尝试使用该array.sort
功能,但它放在"2.0.1.10"
前面"2.0.1.5"
。我不确定为什么会这样
我在 Ruby 中有一个数组,其值如下
xs = %w(2.0.0.1
2.0.0.6
2.0.1.10
2.0.1.5
2.0.0.8)
等等。我想对数组进行排序,最终结果应该是这样的:
ys = %w(2.0.0.1
2.0.0.6
2.0.0.8
2.0.1.5
2.0.1.10)
我曾尝试使用该array.sort
功能,但它放在"2.0.1.10"
前面"2.0.1.5"
。我不确定为什么会这样
使用Schwartzian 变换( Enumerable#sort_by ),并利用整数数组 ( Array#<=> ) 定义的字典顺序:
sorted_ips = ips.sort_by { |ip| ip.split(".").map(&:to_i) }
你能解释得更详细一点吗
您不能比较包含数字的字符串:"2" > "1"
,是的,但是"11" < "2"
因为字符串是按字典顺序比较的,就像字典中的单词一样。因此,您必须将 ip 转换为可以比较的东西(整数数组)ip.split(".").map(&:to_i)
:. 例如"1.2.10.3"
转换为[1, 2, 10, 3]
. 我们称之为转换f
。
您现在可以使用Enumerable#sort
: ips.sort { |ip1, ip2| f(ip1) <=> f(ip2) }
,但始终检查是否Enumerable#sort_by
可以使用更高的抽象。在这种情况下:ips.sort_by { |ip| f(ip) }
。您可以将其理解为“ips
按映射定义的顺序对它们进行排序f
”。
通过拆分将数据拆分为块'.'
。没有标准函数可以这样做,因此您需要编写自定义排序来执行此操作。
2.0.1.10
并且您之前所说的行为2.0.1.5
是预期的,因为它将数据作为字符串并进行 ASCII 比较,从而导致您看到的结果。
arr1 = "2.0.0.1".split('.')
arr2 = "2.0.0.6".split('.')
arr1
对于输入中的所有数据,arr2
逐个元素进行比较。