31

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#?

2
  • Do you have a max length for each substring? Commented Jan 24, 2011 at 16:01
  • And Alignment Component in C#6: stackoverflow.com/a/44427387/2946329 Commented Jun 8, 2017 at 6:05

7 Answers 7

48

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)

Sign up to request clarification or add additional context in comments.

3 Comments

Also note, this only works if you are using a monospaced font. If it's not, the characters may not line up.
any suggestions on how to handle non mono-spaced fonts?
@Choco: Use text APIs from whichever platform you're drawing with.
7

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));

Comments

6

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;
}

Comments

5

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

1 Comment

thanks, i was looking for this. It would have never crossed my mind to , on the interpolation but it is actually really clever (and similar to what string format was already doing)
1

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

Comments

1

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.

Comments

0

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.

2 Comments

I am combining the three strings and storing them in an Access database.
Sure, but ultimately the strings will need to be displayed somewhere to the user, otherwise there is little point in tabulating them. So, when they get displayed, you will need to use a non-proportional font.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.