0

I create loop to create many columns.

My formula:

[dt.Columns.Add("Name" + "{a, b, c}" + {1, 2, 3, 4})]

I have input k = 3 is create 3 columns start with Name, Class, Score.

And here my first code(it not working):

char charac = 'A';
for (int k = 0; k < 3; k++)
{
    for (int m = 0; m < 4; m++)
    {
        charac++;
        dt.Columns.Add("Name" + charac + m);
        dt.Columns.Add("Class" + charac + m);
        dt.Columns.Add("Score" + charac + m);
    }
}

I want result like:

dt.Columns.Add("Name_a1");
dt.Columns.Add("Name_a2");
dt.Columns.Add("Name_a3");
dt.Columns.Add("Name_a4");

dt.Columns.Add("Name_b1");
dt.Columns.Add("Name_b2");
dt.Columns.Add("Name_b3");
dt.Columns.Add("Name_b4");

dt.Columns.Add("Name_c1");
dt.Columns.Add("Name_c2");
dt.Columns.Add("Name_c3");
dt.Columns.Add("Name_c4");


dt.Columns.Add("Class_a1");
dt.Columns.Add("Class_a2");
dt.Columns.Add("Class_a3");
dt.Columns.Add("Class_a4");

dt.Columns.Add("Class_b1");
dt.Columns.Add("Class_b2");
dt.Columns.Add("Class_b3");
dt.Columns.Add("Class_b4");

dt.Columns.Add("Class_c1");
dt.Columns.Add("Class_c2");
dt.Columns.Add("Class_c3");
dt.Columns.Add("Class_c4");


dt.Columns.Add("Score_a1");
dt.Columns.Add("Score_a2");
dt.Columns.Add("Score_a3");
dt.Columns.Add("Score_a4");

dt.Columns.Add("Score_b1");
dt.Columns.Add("Score_b2");
dt.Columns.Add("Score_b3");
dt.Columns.Add("Score_b4");

dt.Columns.Add("Score_c1");
dt.Columns.Add("Score_c2");
dt.Columns.Add("Score_c3");
dt.Columns.Add("Score_c4");
3
  • What output are you getting? Commented Jul 8, 2016 at 10:56
  • 2
    My guess - charac++; shouldn't be inside the inner for but outside Commented Jul 8, 2016 at 10:57
  • 2
    Surely charac++; should be in the outer loop, not the inner one? (although that's a pretty horrible way of handling that part) Commented Jul 8, 2016 at 10:58

7 Answers 7

7

Based on your requirements, your code should look like:

char charac = 'A';
for (int k = 1; k <= 3; k++)
{
    for (int m = 1; m <= 4; m++)
    {
        dt.Columns.Add("Name_" + charac + m);
        dt.Columns.Add("Class_" + charac + m);
        dt.Columns.Add("Score_" + charac + m);
    }

    charac++;
}

Errors you've made:

  1. You've incremented charac in incorrect place (should be at the end of outer loop. not in the begin of inner one).
  2. Loops should start from 1, not from zero. Also "upper bound" of loop counter should be included.

Update. In the case when columns order matters - you need separate loop for each column prefix. To avoid code copying, this can be refactored into method:

private void AddColumns(DataTable dt, string columnPrefix)
{
    char charac = 'A';
    for (int k = 1; k <= 3; k++)
    {
        for (int m = 1; m <= 4; m++)
        {
            dt.Columns.Add(columnPrefix + charac + m);
        }

        charac++;
    }
}

and use this method as

AddColumns(dt, "Name_");
AddColumns(dt, "Class_");
AddColumns(dt, "Score_");
Sign up to request clarification or add additional context in comments.

9 Comments

Actually, to get the order that is in the question, you'd probably need separate loops for Name_, Class_, Score_
@MarcGravell well, you're right - if order of columns matters. ;) The very first thing I've seen - is totally incorrect naming produced by OP's code thus possible incorrect order was not taken into account.
Have any method to sort like: Name_a1 Name_a2 Name_a3 Name_a4? Your code right but it sort like: Name_a1, Class_a1, Score_a
@VănLộc that's exactly the essence of Marc's comment. You need separate loops for Name_, Class_ and Score_, not one common loop.
Starting at 0 and using a less than condition is just as valid here as starting and 1 and using a less than equal to condition.
|
3

I suggest using nested loops:

string[] names = new string[] {
  "Name", "Class", "Score"};

foreach (string name in names)
  for (char charac = 'A'; charac <= 'C'; ++charac){
    for (int m = 1; m <= 4; ++m)
      dt.Columns.Add(String.Format("{0}_{1}{2}", name, charac, m));

2 Comments

Using three for loop will make program slow?
@VănLộc that doesn't change the amount of work actually being done, though, and these loops are tiny - so: no
3

Store them in collections and use foreach loops:

List<string> letters = new List<string> { "a", "b", "c" };
List<string> types = new List<string> { "Name", "Class", "Score" };
List<int> ints = Enumerable.Range(1, 4).ToList();

foreach (string type in types)
{
    foreach (string letter in letters)
    {
        foreach (int i in ints)
        {
            dt.Columns.Add($"{type}_{letter}{i}");
        }
    }
}

1 Comment

You don't need the ToString call on i.
2

Define the characters in a collection. I also made some changes to the rest of your code.

char[] chars = new char[3] { 'a', 'b', 'c'};
for (int k = 0; k < chars.Length; k++)
{
   var c = chars[k];
    for (int m = 1; m <= 4; m++)
    {
        dt.Columns.Add("Name" + "_" + c + m);
        dt.Columns.Add("Class" + "_" + c + m);
        dt.Columns.Add("Score" + "_" + c + m);
    }
}

1 Comment

Thanks your reply. Awesome!
2

Try this,

        DataTable dt =new DataTable();

        char[] charac = {'A','B','C'};

        for (int k = 0; k < 3; k++)
        {

            for (int m = 0; m < 3; m++)
            {                    
                dt.Columns.Add("Name_" + charac[k]+(m+1));
                dt.Columns.Add("Class_" + charac[k]+(m+1));
                dt.Columns.Add("Score_" + charac[k]+(m+1));
            }

        }

Comments

2

There are a lot of answers here with explicit loops - here's a way to do it with a LINQ method chain:

var groups = new[] { "Name", "Class", "Score" };
var letters = new[] { "a", "b", "c" };
var range = Enumerable.Range(1, 4);

foreach(var column in groups
    .Join(letters, s => true, s => true, (prefix, letter) => $"{prefix}_{letter}")
    .Join(range, s => true,s => true,(prefix, i) => $"{prefix}{i}"))
{
    dt.Columns.Add(column);
}

Nice and simple.


Of course, the .Join(..., s => true, s => true, ...) to get a full cartesian product is a little clunky - but it's quite easy to hide it in an extension method:

public static class EnumerableExtensions
{
    public static IEnumerable<T3> CrossJoin<T, T2, T3>(
        this IEnumerable<T> source,
        IEnumerable<T2> other,
        Func<T, T2, T3> resultSelector)
    {
        return source.Join(other, x => true, x => true, resultSelector);
    }
}

resulting in the actual implementation being

var groups = new[] { "Name", "Class", "Score" };
var letters = new[] { "a", "b", "c" };
var range = Enumerable.Range(1, 4);

foreach(var column in groups
    .CrossJoin(letters, (prefix, letter) => $"{prefix}_{letter}")
    .CrossJoin(range, (str, i) => $"{str}{i}"))
{
    dt.Columns.Add(column);
}

This has the correct order of the elements, and has the additional benefit that it's easy to add sorting, transformation, filtering etc at the end of the pipeline, since it's just a single IEnumerable<string> that you're looping over.

Comments

1

Try this code, it works fine and is quite simple to understand. Actually it's just the modified version of your code.

Creating a method would be required in order to avoid the extra loops for the sequence.

    private void AddCols(DataTable dt, string Name)
{
    char charac = 'A';
    for (int k = 1; k <= 3; k++)
    {
        for (int m = 1; m <= 4; m++)
        {
            dt.Columns.Add(columnPrefix + charac + m);
        }

        charac++;
    }
}

5 Comments

Why is there a third loop?
l is variable custom I assign from other class. If I change this, I must change conditional.
Your code work correct. But it has obscure for me. Please update answer to improve. Thanks.
Yeah actually third loop is not required if character list or array is used. My bad :( Anyways thanks for the suggestion and comments :)
@JDoshi when you're copying other answers - at least don't screw it up. You've changed method parameter name to Name but left it as-is in method body, thus your code sample will not ever compile.

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.