Padding gedruckte Ausgabe von tabellarischen Daten
-
03-07-2019 - |
Frage
Ich weiß, dies ist wahrscheinlich tot ist einfach, aber ich habe einige Daten bekam, wie diese in einer Datei:
Artichoke
Green Globe, Imperial Star, Violetto
24" deep
Beans, Lima
Bush Baby, Bush Lima, Fordhook, Fordhook 242
12" wide x 8-10" deep
, dass ich möchte in der Lage sein, zu formatieren, in einem netten TSV Art der Tabelle etwas wie folgt aussehen:
Name | Varieties | Container Data
----------|------------- |-------
some data here nicely padded with even spacing and right aligned text
Lösung
Dies ist ein einigermaßen vollständiges Beispiel, dass die folgende
übernimmt- Die Liste der Produkte wird in einer Datei namens veg.txt
- Ihre Daten werden über drei Zeilen pro Datensatz mit den Feldern in aufeinander folgenden Zeilen angeordnet
Ich bin ein bisschen ein Noob zu den Schienen so gibt es zweifellos besser und elegante Art und Weise, dies zu tun
#!/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
Die folgende Beispieldatei
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
Produziert die folgende Ausgabe
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
Andere Tipps
Versuchen Sie String#rjust(width)
:
"hello".rjust(20) #=> " hello"
Ich schrieb ein Juwel zu tun genau das: http://tableprintgem.com
Niemand hat die „coolsten“ / kompakteste Weise erwähnt - den %
Operator - zum Beispiel: "%10s %10s" % [1, 2]
. Hier ist ein Code:
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 }
Gibt:
This code is indeed very compact and I hope you will find it helpful!
Hier ist der Code aus mehr lesbar:
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
ein weiteres Juwel: https://github.com/visionmedia/terminal-table Terminal Tabelle ist ein schneller und einfacher, aber reich an Funktionen ASCII-Tabelle Generator in Ruby geschrieben.
Ich habe eine kleine Funktion einen 2D-Array als Tabelle zu drucken. Jede Zeile muss die gleiche Anzahl von Spalten für diese zu arbeiten. Es ist auch einfach auf Ihre Bedürfnisse zu optimieren.
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
Kernel.sprintf sollten Sie beginnen.