Relleno de la salida impresa de los datos tabulares

Sé que esto es probablemente muertos simple, pero tengo algunos datos como esta en un archivo:

Artichoke

Green Globe, Imperial Star, Violetto

24" deep

Beans, Lima

Bush Baby, Bush Lima, Fordhook, Fordhook 242

12" wide x 8-10" deep

que me gustaría ser capaz de formato en un bonito TSV tipo de mesa, mirar algo como esto:

    Name  | Varieties    | Container Data
---------- | ------------- |-------
some data here nicely padded with even spacing and right aligned text 

OriginalEl autor The Pied Pipes | 2009-03-02

7 respuestas

  1. 7

    Este es un razonablemente completo ejemplo, que asume el siguiente

    • Su lista de productos se encuentra en un archivo llamado veg.txt
    • Los datos se organizan a través de tres líneas por cada registro con los campos en líneas consecutivas

    Yo soy un poco noob a rails, por lo que sin duda hay mejores y más elegantes maneras de hacer esto

    #!/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

    El siguiente ejemplo de archivo de

    Alcachofa 
    Green Globe, Imperial Star, Violetto 
    24" de profundidad 
    Frijoles, Lima 
    Baby Bush, Bush Lima, Fordhook, Fordhook 242 
    12" de ancho x 8-10" de profundidad 
    Patatas 
    El Rey Eduardo, Desiree, Jersey Real 
    36" de ancho x 8-10" de profundidad 
    

    Produce la siguiente salida

     Nombre De La Variedad De Contenedores 
    ---- ------- --------- 
    La alcachofa de Green Globe, Imperial Star, Violetto 24" de profundidad 
    Frijoles, Habas Baby Bush, Bush Lima, Fordhook, Fordhook 242 12" de ancho x 8-10" de profundidad 
    Patatas Rey Edward, Desiree, Jersey Real de 36" de ancho x 8-10" de profundidad 
    
    Bueno, Sweet61. Voy a cambiar el Vegetal classname a TableFormatter o similares y, a continuación, voy a tener alguna clase reutilizable sistema. Saludos! andy
    Pensé acerca de esto y después de que usted podría anular to_s en los Vegetales de la clase para hacer la impresión, a continuación, el bucle al final sería mucho más sencillo

    OriginalEl autor Steve Weet

  2. 18

    Escribí una joya para hacer exactamente esto: http://tableprintgem.com

    Esto se ve muy bien, gracias!
    Gran joya, gracias por hacerlo. Hace exactamente lo que necesito!
    Fresco joya, pero mis datos son sólo de una matriz. ¿Se puede hacer?
    Impresionante JOYA gracias

    OriginalEl autor Chris Doyle

  3. 16

    Nadie ha mencionado las más “cool” de la mayoría de manera compacta, usando de la % operador, por ejemplo: "%10s %10s" % [1, 2]. Aquí está el código:

    xs = [ 
    ["Este código", "es", "de hecho"], 
    ["muy", "pacto", "y"], 
    ["Espero", "encontrar", "útil!"], 
    ] 
    m = xs.map { |_| _.longitud } 
    xs.cada { |_| _.each_with_index { |e, i| s = e.tamaño; m[i] = s si s > m[i] } } 
    xs.cada { |x| pone m.mapa { |_| "%#{_}s" }.join(" " * 5) % x } 
    

    Da:

     Este código es de hecho 
    muy compacto y 
    Espero que usted encontrará que es útil! 
    

    Aquí es el código más legible:

    max_lengths = xs.map { |_| _.longitud } 
    xs.hacer cada uno |x| 
    x.each_with_index hacer |e, i| 
    s = e.tamaño 
    max_lengths[i] = s si s > max_lengths[i] 
    final 
    final 
    xs.hacer cada uno |x| 
    formato = max_lengths.mapa { |_| "%#{_}s" }.join(" " * 5) 
    pone de formato % x 
    final 
    
    Esta es una gran solución. Yo lo hice en cuenta sin embargo, que la m = xs.map { |_| _.length } código sólo funciona en este ejemplo por casualidad. el _.la longitud de este ejemplo es en realidad devolver el número de elementos de la matriz. Suponiendo que hay siempre al menos 1 elemento y todos los elementos tienen el mismo número de entradas, realmente te quieren m = xs[0].map { |_| _.length }
    Esto realmente se destaca. Sin embargo, no deberíamos calcular max_lengths según el número de filas, sino que debe en el número de columnas. Lo que quiero decir es que, en lugar de: max_lengths = xs.map { |_| _.length }, deberíamos hacer: max_lengths = Array.new(xs[0].length, 0)

    OriginalEl autor David J.

  4. 3

    Tengo una pequeña función para imprimir una matriz 2D como una tabla. Cada fila debe tener el mismo número de columnas para que esto funcione. También es fácil de ajustar a sus necesidades.

    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

    OriginalEl autor roshanjames

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *