Monday, April 11, 2011

Padding printed output of tabular data

Man, I know this is probably dead simple, but I've got some data such as this in one file:

Artichoke

Green Globe, Imperial Star, Violetto

24" deep

Beans, Lima

Bush Baby, Bush Lima, Fordhook, Fordhook 242

12" wide x 8-10" deep

that I'd like to be able to format into a nice TSV type of table, to look something like this:

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

in Ruby...

can anyone help me out?

tia.

From stackoverflow
  • Kernel.sprintf should get you started.

  • Try String#rjust(width).

    -- MarkusQ

  • This is a reasonably full example that assumes the following

    • Your list of products is contained in a file called veg.txt
    • Your data is arranged across three lines per record with the fields on consecutive lines

    I am a bit of a noob to rails so there are undoubtedly better and more elegant ways to do this

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

    The following sample file

    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
    

    Produced the following output

           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
    
    The Pied Pipes : Nice one, Sweet61. I'll just change the Vegetable classname to TableFormatter or similar and then I'll have some reusable class system. Cheers! andy
    Steve Weet : I thought about this afterwards and you could override to_s in the Vegetable class to do the printing then the loop at the end would be much simpler

0 comments:

Post a Comment