Rembourrage de la sortie imprimée des données tabulaires
-
03-07-2019 - |
Question
Je sais que c'est probablement très simple, mais j'ai quelques données de ce type dans un fichier:
Artichoke
Green Globe, Imperial Star, Violetto
24" deep
Beans, Lima
Bush Baby, Bush Lima, Fordhook, Fordhook 242
12" wide x 8-10" deep
que j'aimerais pouvoir mettre en forme dans une belle table de type TSV, pour ressembler à ceci:
Name | Varieties | Container Data
----------|------------- |-------
some data here nicely padded with even spacing and right aligned text
La solution
Ceci est un exemple raisonnablement complet qui suppose les éléments suivants
- Votre liste de produits est contenue dans un fichier nommé veg.txt
- Vos données sont réparties sur trois lignes par enregistrement avec les champs sur des lignes consécutives
Je suis un peu un noob aux rails donc il y a sans aucun doute des façons meilleures et plus élégantes de le faire
#!/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
Le fichier exemple suivant
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
Produit la sortie suivante
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
Autres conseils
Essayez String # rjust ( largeur)
:
"hello".rjust(20) #=> " hello"
J'ai écrit un bijou pour faire exactement cela: http://tableprintgem.com
Personne n’a mentionné le "plus cool" / moyen le plus compact - en utilisant l'opérateur %
- par exemple: "% 10s% 10s " % [1, 2]
. Voici du 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 }
donne:
This code is indeed very compact and I hope you will find it helpful!
Voici le code rendu plus lisible:
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
un autre joyau: https://github.com/visionmedia/terminal-table Terminal Table est un générateur de table ASCII rapide et simple, mais riche en fonctionnalités, écrit en Ruby.
J'ai une petite fonction pour imprimer un tableau 2D sous forme de tableau. Chaque ligne doit avoir le même nombre de colonnes pour que cela fonctionne. Il est également facile de modifier vos besoins.
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 devrait vous aider à démarrer.