Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create all combinations of n*m values

Tags:

c#

linq

Say I have a data structure of IEnumerable<IEnumerable<object>> like this:

{
    { A, B }
    { 1, 2, 3 }
    { Z }
}

Where the outer array can contain any number of inner arrays. And the inner arrays can each independently contain any number of elements. And assume, for the sake of simplicity, that no array will be empty.

And I want to transform it to a IEnumerable<IEnumerable<object>> like this:

{ { A, 1, Z }, { A, 2, Z }, { A, 3, Z }, { B, 1, Z }, { B, 2, Z }, { B, 3, Z } }

Which contains every combination of the values from the original structure. So each element in each inner array maps by index to an element/array in the original outer array.

What is the simplest way to do that in C#?

like image 889
Andrew Russell Avatar asked Apr 15 '11 10:04

Andrew Russell


People also ask

How do you make all combinations in R?

To create combination of multiple vectors, we can use expand. grid function. For example, if we have six vectors say x, y, z, a, b, and c then the combination of vectors can be created by using the command expand.


2 Answers

You could use CartesianProduct method by Eric Lippert for this (taken from here):

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}));                
}
like image 52
Oleks Avatar answered Oct 14 '22 05:10

Oleks


private static IEnumerable<IEnumerable<object>> GetAllCombinations(IEnumerable<IEnumerable<object>> a)
    {
        if (!a.Skip(1).Any())
        {
            return a.First().Select(x => new[] { x });
        }

        var tail = GetAllCombinations(a.Skip(1)).ToArray();
        return a.First().SelectMany(f => tail.Select(x => new[] { f }.Concat(x)));
    }
like image 31
Steck Avatar answered Oct 14 '22 05:10

Steck