2

I have a question related to the combination.

I am actually developing a ecommerce site and I have a function to allow customer create product variant.

For example: Black Pant 34W 30L, Black Pant 38W 32L, White Pant 34W 30l. Those are defined as product variants.

Assume my pant has 3 options, and they are color, waist size and length.

I now have 3 list.

ListA = {"black", "white", "red"} //For the color
ListB = {30,32,34,36,38} //For the waist
ListC ={28,30,32,34} //For the length

My question is how can I list all the possible combinations?

My desired result should be look like {{black,30,28},{black,30,30},{black,30,32},{white,34 ,30}}

P.S. The tricky part is that I don't know how many options customer will assign to this product. The count of the option might be just 1, which is the easiest; it could be more than 3...

Problem Solved

Since we don't know how many options we will have. Therefore, we don't know how many for loop we are going to use. In other word, it turns to a typical Cartesian Products.

For more information, you can read from these two links. http://www.interact-sw.co.uk/iangblog/2010/07/28/linq-cartesian-1 http://blogs.msdn.com/b/ericlippert/archive/2010/06/28/computing-a-cartesian-product-with-linq.aspx

Thank you for all your help!

HorseKing
  • 454
  • 6
  • 19
  • 2
    http://blogs.msdn.com/b/ericlippert/archive/2010/06/28/computing-a-cartesian-product-with-linq.aspx Seems relevant – dlev Jun 08 '13 at 06:03
  • 1
    Have you looked at how other ecommerce system do it? dashCommerce has a similar option to generate SKUs from product variants. – Tim Long Jun 08 '13 at 06:05
  • I did got a NopCommerce and learned some idea from it. – HorseKing Jun 08 '13 at 06:09
  • Many thanks to both of you. Thank you very much for the clue. Cartesian Products is the keyword! – HorseKing Jun 08 '13 at 06:12

1 Answers1

7

As stated in the comments Eric Lippert has a blog post named Computing a Cartesian Product with LINQ that explains how to solve your problem. You need an extension method to compute the cartesian product:

public static IEnumerable<IEnumerable<T>> CartesianProduct<T>(this IEnumerable<IEnumerable<T>> sequences) {
  IEnumerable<IEnumerable<T>> result = new [] { Enumerable.Empty<T>() };
  foreach (var sequence in sequences) {
    var localSequence = sequence;
    result = result.SelectMany(
      _ => localSequence,
      (seq, item) => seq.Concat(new[] { item })
    );
  }
  return result;
}

Then you need a sequence of sequences to perform the product over. In your case you have both strings and integers in your sequences so the common base type T has to be Object.

var sequences = new[] {
  new Object[] { "black", "white", "red" },
  new Object[] { 30, 32, 34, 36, 38 },
  new Object[] { 28, 30, 32, 34 }
};

To compute the Cartesian product you simply invoke the extension method:

var result = sequences.CartesianProduct();

When you enumerate the result it is computed on the fly (lazily). If you prefer to create a list of lists you need to call ToList() after Concat and also before returning result from the extension method.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
Martin Liversage
  • 104,481
  • 22
  • 209
  • 256