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 
Était-ce utile?

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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top