我在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"
之前。我不确定为什么会发生这种情况
答案 0 :(得分:18)
使用Schwartzian transform(Enumerable#sort_by),并利用整数数组(lexicographical order)定义的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
映射定义的顺序对其进行排序。”
答案 1 :(得分:1)
通过拆分'.'
将数据拆分为多个块。这样做没有标准功能,因此您需要编写自定义排序来执行此操作。
您在2.0.1.10
之前所说的关于2.0.1.5
的行为是预期的,因为它将数据作为字符串并进行ASCII比较,从而导致您看到的结果。
arr1 = "2.0.0.1".split('.')
arr2 = "2.0.0.6".split('.')
对于输入中的所有数据,逐元素地比较arr1
和arr2
。