Во-первых, ваш образец кода может работать, но на это не на что вы рассчитываете положиться.
Я бы написать
pipe = File.open('pipe.txt', 'r')
alpha = pipe.sort { |a, b| a <=> b }
puts alpha
как:
alpha = File.readlines('pipe.txt').sort
Разница заключается в том, что с помощью open
и сортировки ручки оставляет ручка открыть файл. Висячие файловые дескрипторы могут потреблять все доступные дескрипторы системы, что создает проблемы при выполнении длительных задач, поэтому привыкайте к методам или конструкциям, которые автоматически закрывают файлы, когда они будут выполнены, или убедитесь, что вы явно закрываете файл , Использование readlines
автоматически возвращает массив строк И закрывает файл, когда он закончил чтение. Затем этот массив передается в sort
.
A bare 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'
:
Глядя на фактические значения:
'a b'.chars.map(&:ord) # => [97, 32, 98]
'a b'.chars.map(&:ord) # => [97, 32, 32, 98]
Итак, поэтому мы хотим разделить линии на свои значения, чтобы отрицать эффект разделителей.
Двигаясь дальше, разделение линий не обязательно, что вы хотите сделать в «универсальном» методе, хотя вы могли бы. И я не собираюсь писать все это для вас, но я укажу путь.
«comma.txt» может быть проанализирован с использованием встроенной библиотеки CSV. «CSV» означает «Comma Separated Values». В документации уже есть пример, показывающий, как анализировать строки из файла или из строки. Я использую строчную версию, но вы хотите изменить ее, чтобы использовать версию файла. В качестве исходного теста, это показывает, что мы можем сортировать подмассивы и получить желаемые результаты:
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"]]