首先,您的示例代码可能有效,但您不想依赖它。
我会写
pipe = File.open('pipe.txt', 'r')
alpha = pipe.sort { |a, b| a <=> b }
puts alpha
作为:
alpha = File.readlines('pipe.txt').sort
不同之处在于使用open 并对句柄进行排序会使文件句柄保持打开状态。悬空文件句柄会消耗系统上所有可用的句柄,从而导致长时间运行的任务出现问题,因此请养成使用方法或构造的习惯,这些方法或构造会在文件完成后自动关闭文件,或者确保明确关闭文件.使用readlines 会自动返回一个行数组,并在完成读取时关闭文件。然后将该数组传递给sort。
裸sort 将自动使用与{ |a, b| a <=> b } 相同的块,因此这是多余的,不需要。
您的代码按整个字符串排序,但这并不是您真正想要的。相反,您必须将行分成组件列,然后按这些列排序。考虑一下:
ary = [
'a b',
'a b'
].sort
ary # => ["a b", "a b"]
从表面上看,'a b' 似乎与'a b' 或之后相同,但由于' ' 的ASCII 值低于b,'a b' 最终在'a b' 之前进行排序:
' '.ord # => 32
'b'.ord # => 98
查看实际值:
'a b'.chars.map(&:ord) # => [97, 32, 98]
'a b'.chars.map(&:ord) # => [97, 32, 32, 98]
所以,这就是为什么我们要将行拆分为它们的值,以消除分隔符的影响。
继续说,分割线并不是你想在“通用”方法中做的事情,尽管你可以。而且,我不打算为你写这一切,但我会指出方向。
"comma.txt" 可以使用内置的CSV 库进行干净的解析。 “CSV”代表“逗号分隔值”。该文档已经有一个示例显示如何从文件或字符串中解析行。我使用的是字符串版本,但您想修改它以使用文件版本。作为一个开始测试,这表明我们可以对子数组进行排序并获得所需的结果:
text = 'a,b,c
a,a,b
a,a,a
'
require 'csv'
ary = []
CSV.parse(text) do |row|
ary << row
end
ary.sort
# => [["a", "a", "a"], ["a", "a", "b"], ["a", "b", "c"]]
现在可以将行拆分为组件字段,一切正常:
text = 'Abercrombie, Neil, Male, Tan, 2/13/1943
Bishop, Timothy, Male, Yellow, 4/23/1967
Kelly, Sue, Female, Pink, 7/12/1959
'
require 'csv'
ary = []
CSV.parse(text) do |row|
ary << row
end
ary.sort
# => [["Abercrombie", " Neil", " Male", " Tan", " 2/13/1943"],
# ["Bishop", " Timothy", " Male", " Yellow", " 4/23/1967"],
# ["Kelly", " Sue", " Female", " Pink", " 7/12/1959"]]
请注意,这些字段保留了它们的前导空格。您可以在各个字段上使用strip 来删除前导和尾随空格,或者map(&:strip)。如何做到这一点由您自己决定。
处理pipes.txt几乎一样,只需要告诉CSV如何解释列:
text = 'Smith | Steve | D | M | Red | 3-3-1985
Bonk | Radek | S | M | Green | 6-3-1978
Bouillon | Francis | G | M | Blue | 6-3-1975
'
require 'csv'
ary = []
CSV.parse(text, col_sep: '|') do |row|
ary << row
end
ary.sort
# => [["Bonk ", " Radek ", " S ", " M ", " Green ", " 6-3-1978"],
# ["Bouillon ", " Francis ", " G ", " M ", " Blue ", " 6-3-1975"],
# ["Smith ", " Steve ", " D ", " M ", " Red ", " 3-3-1985"]]
同样,空格被保留,只是现在它们是尾随空格。而且,你还要弄清楚如何处理它们。
处理 text.txt 可能是最直接的:
text = 'Kournikova Anna F F 6-3-1975 Red
Hingis Martina M F 4-2-1979 Green
Seles Monica H F 12-2-1973 Black
'
ary = text.split("\n").map { |row|
row.split
}
puts ary.map{ |r| r.join(',') }
# >> Kournikova,Anna,F,F,6-3-1975,Red
# >> Hingis,Martina,M,F,4-2-1979,Green
# >> Seles,Monica,H,F,12-2-1973,Black
ary.sort
# => [["Hingis", "Martina", "M", "F", "4-2-1979", "Green"],
# ["Kournikova", "Anna", "F", "F", "6-3-1975", "Red"],
# ["Seles", "Monica", "H", "F", "12-2-1973", "Black"]]