1

I have a list of string in my C# program. However, I know the number of items I have in my list only at runtime.

Let us say, for the sake of simplicity, my list is {{F1, F2, F3},{P1, P2},{A1, A2, A3}} Now I need to generate all possible combinations as follows.

Below is the image of my list

enter image description here

{F1 P1 A1}, {F1 P1 A2}, {F1 P1 A3}, {F1 P2 A1}, {F1 P2 A2}, {F1 P2 A3}, {F2 P1 A1}, {F2 P1 A2}, {F2 P1 A3}, {F2 P2 A1} {F2 P2 A2}, {F2 P2 A3}, {F3 P1 A1}, {F3 P1 A2}, {F3 P1 A3},{F3 P2 A1}, {F3 P2 A2}, {F3 P2 A3}

Can somebody please help with this?

Kirti Zare
  • 719
  • 1
  • 12
  • 35
  • 1
    Are the values within each *sublist* (e.g. `{A1, A2, A3}`) *distinct*? – Dmitry Bychenko Mar 25 '17 at 12:55
  • Possibly duplicate with http://stackoverflow.com/questions/545703/combination-of-listlistint – Liu Mar 25 '17 at 13:05
  • No it is not sublist. Eg. I have list of string. List[0] will be {F1, F2, F3}. List[1] = {P1, P2} and List[2] = {A1, A2, A3}. I Update my question and Add an Image so it will help you to understand it – Kirti Zare Mar 25 '17 at 13:08

1 Answers1

2

Linq-based solution (providing that the list doesn't have null or empty sublists and all values within each sublist considered being unique/distinct):

private static IEnumerable<List<T>> MyEnumerator<T>(List<List<T>> data) {
  List<int> indexes = Enumerable.Repeat(0, data.Count).ToList();

  do {
    yield return indexes
      .Select((value, i) => data[i][value])
      .ToList();

    for (int i = data.Count - 1; i >= 0; --i)
      if (indexes[i] == data[i].Count - 1)
        indexes[i] = 0;
      else {
        indexes[i] += 1;

        break;
      }
  }
  while (indexes.Any(value => value != 0));
}

Test:

  List<List<String>> data = new List<List<string>>() {
    new List<string> { "F1", "F2", "F3"},
    new List<string> { "P1", "P2"},
    new List<string> { "A1", "A2", "A3"},
  };

  var result = MyEnumerator(data).Select(list => "{" + string.Join(", ", list) + "}");

  Console.Write(string.Join(Environment.NewLine, result));

Outcome:

{F1, P1, A1}
{F1, P1, A2}
{F1, P1, A3}
{F1, P2, A1}
{F1, P2, A2}
{F1, P2, A3}
{F2, P1, A1}
{F2, P1, A2}
{F2, P1, A3}
{F2, P2, A1}
{F2, P2, A2}
{F2, P2, A3}
{F3, P1, A1}
{F3, P1, A2}
{F3, P1, A3}
{F3, P2, A1}
{F3, P2, A2}
{F3, P2, A3}

Edit: if you happen to have a List of comma separated strings

  List<string> source = new List<string> {
    "F1,F2,F3",
    "P1,P2",
    "A1,A2,A3",
  };

you can get required List<List<string>> with one Linq more

  List<List<String>> data = source
    .Select(line => line
       .Split(',')
       .Distinct()
       .ToList())
    .ToList();

  var result = MyEnumerator(data).Select(list => "{" + string.Join(", ", list) + "}");

  Console.Write(string.Join(Environment.NewLine, result));
Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215