我有一些txt文件,我需要能够用三种不同的输出解析它们:
以下是所有三个文本文件的示例:
pipe.txt:
Smith | Steve | D | M | Red | 3-3-1985
Bonk | Radek | S | M | Green | 6-3-1978
Bouillon | Francis | G | M | Blue | 6-3-1975
comma.txt:
Abercrombie, Neil, Male, Tan, 2/13/1943
Bishop, Timothy, Male, Yellow, 4/23/1967
Kelly, Sue, Female, Pink, 7/12/1959
space.txt:
Kournikova Anna F F 6-3-1975 Red
Hingis Martina M F 4-2-1979 Green
Seles Monica H F 12-2-1973 Black
我能够通过写这个来按字母顺序排序pipe.txt:
pipe = File.open('pipe.txt', 'r')
alpha = pipe.sort { |a, b| a <=> b }
puts alpha
我没有运气搞清楚其他事情。任何帮助将不胜感激。
答案 0 :(得分:0)
首先,您的示例代码可能有效,但它并不是您想要依赖的东西。
我写了
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
,{{ 1}}在'a b'
:
'a b'
查看实际值:
' '.ord # => 32
'b'.ord # => 98
那么,这就是为什么我们要将线条划分为它们的值,以否定分隔符的效果。
继续前进,分割线条并不是你想要在&#34;通用&#34;中做的事情。方法,尽管你可以。而且,我不打算为你写一切,但我会指出方向。
&#34; comma.txt&#34;可以使用内置的CSV库干净地解析。 &#34; CSV&#34;代表&#34;逗号分隔价值&#34;。该文档已经有一个示例,说明如何从文件或字符串中解析行。我使用的是字符串版本,但您想修改它以使用文件版本。作为一个开始测试,这表明我们可以对子数组进行排序并获得所需的结果:
'a b'.chars.map(&:ord) # => [97, 32, 98]
'a b'.chars.map(&:ord) # => [97, 32, 32, 98]
现在可以将行拆分成组件字段,事情应该有效:
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
。由你决定如何做到这一点。
处理pipes.txt几乎是一样的,只需告诉CSV如何解释列:
map(&:strip)
同样,空格被保留,现在它们只是尾随空格。而且,再一次,你要弄清楚如何处理它们。
处理text.txt可能是最直接的:
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"]]
答案 1 :(得分:0)
最简单的方法是使用csv格式,让库将数据解析到单独的字段中。
这是一个显示3个排序顺序的示例脚本
require 'csv'
require 'date'
data = CSV.parse(DATA)
SurnameIndex = 0
GenderIndex = 2
DateIndex = 4
puts "By gender then surname: %s" % data.sort_by.sort_by { |object| [ object[GenderIndex], object[SurnameIndex] ] }.inspect
puts "By birth date: %s" % data.sort_by.sort_by { |object| Date.strptime(object[DateIndex], '%m/%d/%Y') }.inspect
puts "By surname descending: %s" % data.sort_by.sort { |a, b| b[SurnameIndex] <=> a[SurnameIndex] }.inspect
__END__
Abercrombie,Neil,Male,Tan,2/13/1943
Bishop,Timothy,Male,Yellow,4/23/1967
Kelly,Sue,Female,Pink,7/12/1959
请注意,最后一种方法是a
和b
个对象被反转以获得您需要的相反顺序