Je génère un script qui génère des informations sur la console. L'information est une sorte de statistique avec une valeur. Un peu comme un hachage.
Ainsi, le nom d'une valeur peut comporter 8 caractères et un autre 3. Lorsque je passe en boucle la sortie des informations avec deux\t certaines des colonnes ne sont pas alignées correctement.
Ainsi, par exemple, la sortie peut être en tant que telle:
long value name 14
short 12
little 13
tiny 123421
long name again 912421
Je veux que toutes les valeurs soient alignées correctement. En ce moment, je fais ceci:
puts "#{value_name} - \t\t #{value}"
Comment pourrais-je dire pour les noms longs, de n'utiliser qu'un seul onglet? Ou existe-t-il une autre solution?
Il y a généralement un %10s
type de schéma printf
qui formate bien.
Cependant, je n'ai pas utilisé Ruby du tout, donc vous devez vérifier cela.
Oui, il y a printf avec formatage.
L'exemple ci-dessus doit s'aligner à droite dans un espace de 10 caractères.
Vous pouvez formater en fonction de votre champ le plus large dans la colonne.
printf ([port,] format, arg ...)
Imprime des arguments formatés selon le format comme sprintf. Si le premier argument est l'instance de IO ou sa sous-classe, print redirigé vers cet objet. La valeur par défaut est la valeur de $ stdout.
Pourvu que la longueur maximale ne dépasse pas 20 caractères:
printf "%-20s %s\n", value_name, value
Si vous voulez le rendre plus dynamique, quelque chose comme ça devrait bien fonctionner:
longest_key = data_hash.keys.max_by(&:length)
data_hash.each do |key, value|
printf "%-#{longest_key.length}s %s\n", key, value
end
La chaîne a un ljust intégré pour exactement cela:
x = {"foo"=>37, "something long"=>42, "between"=>99}
x.each { |k, v| puts "#{k.ljust(20)} #{v}" }
# Outputs:
# foo 37
# something long 42
# between 99
Ou, si vous voulez des onglets, vous pouvez faire un peu de calcul (en supposant une largeur d'affichage de 8 onglets) et écrire une courte fonction d'affichage:
def tab_pad(label, tab_stop = 4)
label_tabs = label.length / 8
label.ljust(label.length + tab_stop - label_tabs, "\t")
end
x.each { |k, v| puts "#{tab_pad(k)}#{v}" }
# Outputs:
# foo 37
# something long 42
# between 99
Il y avait quelques bogues auparavant, mais maintenant vous pouvez utiliser la plupart de la syntaxe printf avec l'opérateur%:
1.9.3-p194 :025 > " %-20s %05d" % ['hello', 12]
=> " hello 00012"
Bien sûr, vous pouvez également utiliser la largeur précalculée:
1.9.3-p194 :030 > "%-#{width}s %05x" % ['hello', 12]
=> "hello 0000c"
J'ai écrit une chose
[[],[],...]
ou tableau de hachages [{},{},...]
Ne détecte pas les colonnes trop larges pour la fenêtre de la console
lists = [[123, "SDLKFJSLDKFJSLDKFJLSDKJF"], [123456, "ffff"],]
array_maxes
def array_maxes(lists)
lists.reduce([]) do |maxes, list|
list.each_with_index do |value, index|
maxes[index] = [(maxes[index] || 0), value.to_s.length].max
end
maxes
end
end
array_maxes(lists)
# => [6, 24]
puts_arrays_columns
def puts_arrays_columns(lists)
maxes = array_maxes(hashes)
lists.each do |list|
list.each_with_index do |value, index|
print " #{value.to_s.rjust(maxes[index])},"
end
puts
end
end
puts_arrays_columns(lists)
# Output:
# 123, SDLKFJSLDKFJSLDKFJLSDKJF,
# 123456, ffff,
et autre chose
hashes = [
{ "id" => 123, "name" => "SDLKFJSLDKFJSLDKFJLSDKJF" },
{ "id" => 123456, "name" => "ffff" },
]
hash_maxes
def hash_maxes(hashes)
hashes.reduce({}) do |maxes, hash|
hash.keys.each do |key|
maxes[key] = [(maxes[key] || 0), key.to_s.length].max
maxes[key] = [(maxes[key] || 0), hash[key].to_s.length].max
end
maxes
end
end
hash_maxes(hashes)
# => {"id"=>6, "name"=>24}
puts_hashes_columns
def puts_hashes_columns(hashes)
maxes = hash_maxes(hashes)
return if hashes.empty?
# Headers
hashes.first.each do |key, value|
print " #{key.to_s.rjust(maxes[key])},"
end
puts
hashes.each do |hash|
hash.each do |key, value|
print " #{value.to_s.rjust(maxes[key])},"
end
puts
end
end
puts_hashes_columns(hashes)
# Output:
# id, name,
# 123, SDLKFJSLDKFJSLDKFJLSDKJF,
# 123456, ffff,
Edit: corrige les clés de hachage considérées dans la longueur.
hashes = [
{ id: 123, name: "DLKFJSDLKFJSLDKFJSDF", asdfasdf: :a },
{ id: 123456, name: "ffff", asdfasdf: :ab },
]
hash_maxes(hashes)
# => {:id=>6, :name=>20, :asdfasdf=>8}
Vous voulez ajouter des colonnes aux colonnes?
hashes.map{ |h| h.slice(:id, :name) }
# => [
# { id: 123, name: "DLKFJSDLKFJSLDKFJSDF" },
# { id: 123456, name: "ffff" },
#]
Pour référence future et les personnes qui regardent cela ou le trouvent ... Utilisez un joyau. Je suggère https://github.com/wbailey/command_line_reporter
Vous ne voulez généralement pas utiliser d'onglets, vous voulez utiliser des espaces et configurer vous-même vos "colonnes", sinon vous rencontrez ces types de problèmes.