Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create all possible combinations of items in a list using Linq and C# [duplicate]

I have a table of categories:

 Catid | Desciption
 1 | Color
 2 | Size
 3 | Material

And a table of category items

 Catid | Name
 1 | Red
 1 | Blue
 1 | Green
 2 | Small
 2 | Med
 2 l Large
 3 | Cotton
 3 | Silk

I need to loop through all the items and display them in a labels like this:

 Red Small Cotton
 Red Small Silk
 Red Med Cotton
 Red Med Silk
 Red Large Cotton
 Red Large Silk
 Blue Small Cotton
 Blue Small Silk
 Blue Med Cotton
 Blue Med Silk
 Blue Large Cotton
 Blue Large Silk
 Green Small Cotton
 Green Small Silk
 Green Med Cotton
 Green Med Silk
 Green Large Cotton
 Green Large Silk

Please note: There could be more or less categories. It is not predetermined.

Any suggestions? Thank you

like image 700
vts Avatar asked May 09 '12 15:05

vts


People also ask

How do you generate all possible combinations of one list?

Add a Custom Column to and name it List1. Enter the formula =List1. Expand out the new List1 column and then Close & Load the query to a table. The table will have all the combinations of items from both lists and we saved on making a custom column in List1 and avoided using a merge query altogether!

What is all in Linq C#?

The Linq All Operator in C# is used to check whether all the elements of a data source satisfy a given condition or not. If all the elements satisfy the condition, then it returns true else return false. There is no overloaded version is available for the All method.

How do you figure out combinations of a set of characters?

To calculate combinations, we will use the formula nCr = n! / r! * (n - r)!, where n represents the total number of items, and r represents the number of items being chosen at a time.


2 Answers

var result = list.GroupBy(t => t.Id).CartesianProduct();

using the CartesianProduct Extension Method from Eric Lippert's Blog:

static IEnumerable<IEnumerable<T>> CartesianProduct<T>(
  this IEnumerable<IEnumerable<T>> sequences) 
{ 
  IEnumerable<IEnumerable<T>> emptyProduct = new[] { Enumerable.Empty<T>() }; 
  return sequences.Aggregate( 
    emptyProduct, 
    (accumulator, sequence) => 
      from accseq in accumulator 
      from item in sequence 
      select accseq.Concat(new[] {item})); 
}

Example:

var list = new[]
{
    new { Id = 1, Description = "Red"    },
    new { Id = 1, Description = "Blue"   },
    new { Id = 1, Description = "Green"  },
    new { Id = 2, Description = "Small"  },
    new { Id = 2, Description = "Med"    },
    new { Id = 2, Description = "Large"  },
    new { Id = 3, Description = "Cotton" },
    new { Id = 3, Description = "Silk"   },
};

var result = list.GroupBy(t => t.Id).CartesianProduct();

foreach (var item in result)
{
    Console.WriteLine(string.Join(" ", item.Select(x => x.Description)));
}

Output:

Red Small Cotton
Red Small Silk
Red Med Cotton
Red Med Silk
Red Large Cotton
Red Large Silk
Blue Small Cotton
Blue Small Silk
Blue Med Cotton
Blue Med Silk
Blue Large Cotton
Blue Large Silk
Green Small Cotton
Green Small Silk
Green Med Cotton
Green Med Silk
Green Large Cotton
Green Large Silk
like image 55
dtb Avatar answered Sep 20 '22 00:09

dtb


Try using a cross join:

var combo = from l1 in List1
            from l2 in List2
            select new {l1, l2};
like image 31
Pranay Rana Avatar answered Sep 22 '22 00:09

Pranay Rana