fraXis
fraXis

Reputation: 3221

Formatting a C# string with identical spacing in between values

I have 3 strings. The first set of strings are:

"1.0536"  
"2.1"  
"2" 

The second is something like:

"Round"  
"Square"  
"Hex"

And the last are:

"6061-T6"  
"T351"  
"ASF.3.4.5" 

I need to combine the three strings together with identical spacing in between each string. I can't use \t for tabbing as after I combine the strings, I send them to an Access Database.

When I combine the strings they look like:

"1.0536 Round 6061-T6"  
"2.1 Square T351"  
"2 Hex ASF.3.4.5" 

I would really like them to look like this with the same exact amount of spacing in between each string:

"1.0536     Round     6061-T6"
"2.1           Square    T351"
"2              Hex          ASF.3.4.5"

How can I do this with C#?

Upvotes: 31

Views: 58523

Answers (7)

brandonstrong
brandonstrong

Reputation: 688

I know this has long since been answered, but there is a new way as of C# 6.0

string[] one = new string[] { "1.0536", "2.1", "2" };
string[] two = new string[] { "Round", "Square", "Hex" };
string[] three = new string[] { "1.0536 Round 6061-T6", "2.1 Square T351", "2 Hex ASF.3.4.5" };

for (int i = 0; i < 3; i++) Console.WriteLine($"{one[i],-10}{two[i],-10}{three[i],-10}");

The $"{one[i],-10}{two[i],-10}{three[i],-10}" is the new replacement for string.format . I have found it very useful in many of my projects. Here is a link to more information about string interpolation in c# 6.0: https://learn.microsoft.com/en-us/dotnet/csharp/tutorials/string-interpolation

Upvotes: 5

drzaus
drzaus

Reputation: 24994

To make life easier, utility methods:

Usage

var data = new[] {
    new[] { "ID", "NAME", "DESCRIPTION" },
    new[] { "1", "Frank Foo", "lorem ipsum sic dolor" },
    new[] { "2", "Brandon Bar", "amet forthrightly" },
    new[] { "3", "B. Baz", "Yeehah!" }
};

var tabbedData = EvenColumns(20, data);
var tabbedData2 = string.Join("\n", EvenColumns(20, false, data)); // alternate line separator, alignment

Results

ID                  NAME                DESCRIPTION
1                   Frank Foo           lorem ipsum sic dolor
2                   Brandon Bar         amet forthrightly
3                   B. Baz              Yeehah!

ID                NAME         DESCRIPTION
1           Frank Foolorem ipsum sic dolor
2         Brandon Bar   amet forthrightly
3              B. Baz             Yeehah!

Code

public string EvenColumns(int desiredWidth, IEnumerable<IEnumerable<string>> lists) {
    return string.Join(Environment.NewLine, EvenColumns(desiredWidth, true, lists));
}

public IEnumerable<string> EvenColumns(int desiredWidth, bool rightOrLeft, IEnumerable<IEnumerable<string>> lists) {
    return lists.Select(o => EvenColumns(desiredWidth, rightOrLeft, o.ToArray()));
}

public string EvenColumns(int desiredWidth, bool rightOrLeftAlignment, string[] list, bool fitToItems = false) {
    // right alignment needs "-X" 'width' vs left alignment which is just "X" in the `string.Format` format string
    int columnWidth = (rightOrLeftAlignment ? -1 : 1) *
                        // fit to actual items? this could screw up "evenness" if
                        // one column is longer than the others
                        // and you use this with multiple rows
                        (fitToItems
                            ? Math.Max(desiredWidth, list.Select(o => o.Length).Max())
                            : desiredWidth
                        );

    // make columns for all but the "last" (or first) one
    string format = string.Concat(Enumerable.Range(rightOrLeftAlignment ? 0 : 1, list.Length-1).Select( i => string.Format("{{{0},{1}}}", i, columnWidth) ));

    // then add the "last" one without Alignment
    if(rightOrLeftAlignment) {
        format += "{" + (list.Length-1) + "}";
    }
    else {
        format = "{0}" + format;
    }

    return string.Format(format, list);
}

Specific to the Question

// for fun, assume multidimensional declaration rather than jagged
var data = new[,] {
    { "1.0536", "2.1", "2" },
    { "Round", "Square", "Hex" },
    { "6061-T6", "T351", "ASF.3.4.5" },
};

var tabbedData = EvenColumns(20, Transpose(ToJaggedArray(data)));

with Transpose:

public T[][] Transpose<T>(T[][] original) {
    // flip dimensions
    var h = original.Length;
    var w = original[0].Length;

    var result = new T[h][];
    for (var r = 0; r < h; r++) {
        result[r] = new T[w];
        for (var c = 0; c < w; c++)
        {
            result[r][c] = original[c][r];
        }
    }
    return result;
}

And multidimensional arrays (source):

public T[][] ToJaggedArray<T>(T[,] multiArray) {
    // via https://stackoverflow.com/questions/3010219/jagged-arrays-multidimensional-arrays-conversion-in-asp-net
    var h = multiArray.GetLength(0);
    var w = multiArray.GetLength(1);

    var result = new T[h][];
    for (var r = 0; r < h; r++) {
        result[r] = new T[w];
        for (var c = 0; c < w; c++) {
            result[r][c] = multiArray[r, c];
        }
    }
    return result;
}

Upvotes: 6

Paul Sasik
Paul Sasik

Reputation: 81459

To do it more dynamically you could do something like this: (hardcoding ahead!)

    int padding = 3;
    int maxCol0width = "Hello World!".Length;
    int maxCol1width = "90.345".Length;
    int maxCol2width = "value".Length;

    string fmt0 = "{0,-" + (maxCol0width + padding) + "}";
    string fmt1 = "{1,-" + (maxCol1width + padding) + "}";
    string fmt2 = "{2,-" + (maxCol2width + padding) + "}";

    string fmt = fmt0 + fmt1 + fmt2;

    Console.WriteLine(fmt, "Hello World!", 90.345, "value");
    Console.WriteLine(fmt, "Hi!", 1.2, "X");
    Console.WriteLine(fmt, "Another", 100, "ZZZ");

You will of course need to figure out your max word widths by looping through each column's values. Also the creation of the format string could be significantly cleaned up and shortened.

Upvotes: 1

Polyfun
Polyfun

Reputation: 9639

Also note that you will need to use a non-proportional font for display, otherwise your columns will still not line up properly. Where are you displaying this data? There may be better ways of getting tabular output.

Upvotes: 0

Martin
Martin

Reputation: 40335

If you know the maximum lengths of each column then do the following:

String result = String.Format("{0} {1} {2}", strCol1.PadRight(10), strCol2.PadRight(9), strCol3.PadRight(9));

Upvotes: 7

Julius A
Julius A

Reputation: 39622

Use String.Format("{0,10}", myString)
Where 10 is the number of characters you want

Upvotes: 1

SLaks
SLaks

Reputation: 887413

You can use advanced features of string.Format:

string.Format("{0,-10}{1,-10}{2}", ...)

You can do the same thing by writing str.PadRight(10)

Upvotes: 48

Related Questions