Я знаю, что это, вероятно, мертво просто, но у меня есть некоторые данные, такие как это в одном файле:
Artichoke
Green Globe, Imperial Star, Violetto
24" deep
Beans, Lima
Bush Baby, Bush Lima, Fordhook, Fordhook 242
12" wide x 8-10" deep
что я хотел бы иметь возможность форматировать в таблицу таблицы TSV, чтобы выглядеть примерно так:
Name | Varieties | Container Data
----------|------------- |-------
some data here nicely padded with even spacing and right aligned text
Ответ 1
Это достаточно полный пример, который предполагает следующее
- Список продуктов содержится в файле veg.txt
- Ваши данные расположены по трем строкам на запись с полями в последовательных строках
Я немного напоминаю рельсы, поэтому есть, несомненно, лучшие и более элегантные способы сделать это.
#!/usr/bin/ruby
class Vegetable
@@max_name ||= 0
@@max_variety ||= 0
@@max_container ||= 0
attr_reader :name, :variety, :container
def initialize(name, variety, container)
@name = name
@variety = variety
@container = container
@@max_name = set_max(@name.length, @@max_name)
@@max_variety = set_max(@variety.length, @@max_variety)
@@max_container = set_max(@container.length, @@max_container)
end
def set_max(current, max)
current > max ? current : max
end
def self.max_name
@@max_name
end
def self.max_variety
@@max_variety
end
def self.max_container()
@@max_container
end
end
products = []
File.open("veg.txt") do | file|
while name = file.gets
name = name.strip
variety = file.gets.to_s.strip
container = file.gets.to_s.strip
veg = Vegetable.new(name, variety, container)
products << veg
end
end
format="%#{Vegetable.max_name}s\t%#{Vegetable.max_variety}s\t%#{Vegetable.max_container}s\n"
printf(format, "Name", "Variety", "Container")
printf(format, "----", "-------", "---------")
products.each do |p|
printf(format, p.name, p.variety, p.container)
end
Следующий пример файла
Artichoke
Green Globe, Imperial Star, Violetto
24" deep
Beans, Lima
Bush Baby, Bush Lima, Fordhook, Fordhook 242
12" wide x 8-10" deep
Potatoes
King Edward, Desiree, Jersey Royal
36" wide x 8-10" deep
Произведен следующий выход
Name Variety Container
---- ------- ---------
Artichoke Green Globe, Imperial Star, Violetto 24" deep
Beans, Lima Bush Baby, Bush Lima, Fordhook, Fordhook 242 12" wide x 8-10" deep
Potatoes King Edward, Desiree, Jersey Royal 36" wide x 8-10" deep
Ответ 2
Попробуйте String#rjust(width)
:
"hello".rjust(20) #=> " hello"
Ответ 3
Я написал камень, чтобы сделать именно это: http://tableprintgem.com
Ответ 4
Никто не упомянул "самый крутой" /самый компактный способ - с помощью оператора %
- например: "%10s %10s" % [1, 2]
. Вот какой код:
xs = [
["This code", "is", "indeed"],
["very", "compact", "and"],
["I hope you will", "find", "it helpful!"],
]
m = xs.map { |_| _.length }
xs.each { |_| _.each_with_index { |e, i| s = e.size; m[i] = s if s > m[i] } }
xs.each { |x| puts m.map { |_| "%#{_}s" }.join(" " * 5) % x }
дает:
This code is indeed
very compact and
I hope you will find it helpful!
Вот код, который становится более читаемым:
max_lengths = xs.map { |_| _.length }
xs.each do |x|
x.each_with_index do |e, i|
s = e.size
max_lengths[i] = s if s > max_lengths[i]
end
end
xs.each do |x|
format = max_lengths.map { |_| "%#{_}s" }.join(" " * 5)
puts format % x
end
Ответ 5
У меня есть небольшая функция для печати 2D-массива в виде таблицы. Для каждой строки должно быть одинаковое количество столбцов. Он также легко поддается вашим потребностям.
def print_table(table)
# Calculate widths
widths = []
table.each{|line|
c = 0
line.each{|col|
widths[c] = (widths[c] && widths[c] > col.length) ? widths[c] : col.length
c += 1
}
}
# Indent the last column left.
last = widths.pop()
format = widths.collect{|n| "%#{n}s"}.join(" ")
format += " %-#{last}s\n"
# Print each line.
table.each{|line|
printf format, *line
}
end
Ответ 6
другой драгоценный камень: https://github.com/visionmedia/terminal-table
Terminal Table - это быстрый и простой, но многофункциональный генератор таблицы ASCII, написанный на Ruby.
Ответ 7
Kernel.sprintf должен начать работу.