Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generating a table with columns of equal width (viewed on the console in Xcode)

Tags:

xcode

swift

This is a piece of code that I am using to check my calculations, I am simply writing out these values into the console in Xcode. Each of the arrays is declared with the values that are shown below.

var water_deficit: [Int] = []

The program calculates values for water deficit and appends them into this list (the calculations are not shown)

let months = ["January","Feburary","March","April","May","June","July","August","September","October","November","December"]
let rainfall = [38,94,142,149,236,305,202,82,139,222,178,103]
let raindays = [3,6,8,7,12,16,10,8,12,14,11,7]
for i in 0...11 {
    println("\(months[i]) \t \(rainfall[i]) \t \(raindays[i]) \t \(water_deficit[i])")
}

The output as shown on the console:

Month    Rainfall    Raindays    Water Deficit
January      38      3   38
Feburary     94      6   -18
March    142     8   -8
April    149     7   -1
May      236     12      116
June     305     16      301
July     202     10      202
August   82      8   82
September    139     12      101
October      222     14      203
November     178     11      208
December     103     7   103

As you can see, because the length of the words/numbers are different, the columns are offset. What do I need to do to generate columns of a specific width to avoid this problem?

like image 734
Jack Hayton Avatar asked Feb 10 '23 11:02

Jack Hayton


2 Answers

Try this:

for i in 0...11 {
  let month = (months[i] as NSString).UTF8String
  println(String(format:"%-10s %10d %10d %10d",  month, 
                 rainfall[i], raindays[i], water_deficit[i]))
}

For details un format and format specifiers see here and here.

In let month = (months[i] as NSString).UTF8String I am applying a conversion from String to C String: it is pretty easy to specify a length in the format specifier of a C String, but I don't know how to do it for a String (my guess is that it is not possible).

like image 140
Mario Zannone Avatar answered Feb 11 '23 23:02

Mario Zannone


The trick is to compute right paddings to the left or to the right of a string unit depending on if you want the string to be right or left justified. Here is a quick implementation. (Swift 2.0, Xcode 7 beta3).

  let headings = ["Month    ", "Rainfall", "RainDays", "Water Deficit"]

let months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]

let rainFalls = [38, 94, 142,149,236,305,202, 82, 139, 222, 178, 103]
let rainyDays = [3, 6, 8,7,12,16,10, 8, 12, 14, 11, 7]
let waterDeficits = [38, -18, -8,-1,116,301,202, 82, 101, 203, 208, 103]


func getRightJustifiedStringRepFor(number: Int, refString:String) -> String
{
    let length = refString.utf8.count
    let stringRep = String(number)

    var paddedStringRep : String = ""

    //Build necessary padding
    for  var i = 0 ; i <  (length - stringRep.utf8.count) ; i++
    {
        paddedStringRep += " "
    }

    paddedStringRep += stringRep

    return paddedStringRep
}


let headingsToDisplay = headings.reduce(""){

    (var accummulated : String, item: String) -> String in
    return accummulated  + item +  "\t\t\t"

}

print(headingsToDisplay)

//Get proper aligned months with forward padding as we want them left aligned
let leftJustifiedMonths = months.map{
    (var item: String) -> String in
    let paddingsNeeded = 9 - item.utf8.count  //9 is the  length of lengthy month name
    for var i = 0 ; i < paddingsNeeded ; i++
    {
        item += " "
    }
    return item
}

print("\n")

for i in 0...11
{
    print(leftJustifiedMonths[i], appendNewline:false)
    print("\t\t\t", appendNewline:false)
    print( (getRightJustifiedStringRepFor(rainFalls[i], refString: "Rainfall")), appendNewline:false)
    print("\t\t\t", appendNewline:false)
    print( (getRightJustifiedStringRepFor(rainyDays[i], refString: "RainDays")),appendNewline:false)
    print("\t\t\t", appendNewline:false)
    print( (getRightJustifiedStringRepFor(waterDeficits[i], refString: "Water Deficit")),appendNewline:false)

    print("\n")

}

This outputs:

enter image description here

like image 42
Shripada Avatar answered Feb 11 '23 23:02

Shripada