Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get all possible combinations for n arrays with different number of elements?

I have some number of arrays which is unknown at programming time, maybe it is 3 or 4 or 7 ... each array has some elements, i.e,

a={1 2 3 4}
b={6 7 5 2 1}
c={22 4 6 8 4 8 5 4}
d={....}
e, f, g, ...

I want to get get all possible combinations by sampling one number from each array for example one case is that I pick up "1" from a, "7" from b, first "8" from c, d[3], e[5],... to make "1,7,8,d[3],e[5],...". It's not possible to use nested for loops because I don't know the number of arrays at compile time. If it was known for example 4 arrays (a,b,c,d) I could use 4 loops:

for (int i = 0; i <= a.Length-1; i++)
{
   for (int j = 0; i <= b.Length-1; j++)
   {
      for (int k = 0; i <= c.Length-1; k++)
      {
         for (int m = 0; i <= d.Length-1; m++)
         {
            Response[f++] = a[i].toString()+","+b[j].toString()+","+c[k].toString()+","+d[m].toString();
         }
      }
   }
}

but for different number of arrays, I don't have any idea.

like image 795
user3636337 Avatar asked Jun 03 '14 10:06

user3636337


People also ask

How do you make all possible combinations in an array?

Let the input array be {1, 2, 3, 4, 5} and r be 3. We first fix 1 at index 0 in data[], then recur for remaining indexes, then we fix 2 at index 0 and recur. Finally, we fix 3 and recur for remaining indexes. When number of elements in data[] becomes equal to r (size of a combination), we print data[].

How do you make all possible combinations in C?

C = combntns( v , k ) returns all possible combinations of the set of values v , given combinations of length k .


2 Answers

This works:

Func<
    IEnumerable<IEnumerable<int>>,
    IEnumerable<IEnumerable<int>>> f0 = null;
f0 = xss =>
{
    if (!xss.Any())
    {
        return new [] { Enumerable.Empty<int>() };
    }
    else
    {
        var query =
            from x in xss.First()
            from y in f0(xss.Skip(1))
            select new [] { x }.Concat(y);
        return query;
    }
};

Func<IEnumerable<IEnumerable<int>>, IEnumerable<string>> f =
    xss => f0(xss).Select(xs => String.Join(",", xs));

So if I have this input:

var input = new []
{
    new [] { 1, 2, 3, 4, },
    new [] { 6, 7, 5, 2, 1, },
    new [] { 22, 4, 6, 8, 4, 8, 5, 4, },
};

I can get the results this way:

var results = f(input);

results


Here's a version which simply sums the results, as per the request in the comments:

Func<IEnumerable<IEnumerable<int>>, IEnumerable<int>> f = null;
f = xss =>
{
    if (!xss.Any())
    {
        return new [] { 0 };
    }
    else
    {
        var query =
            from x in xss.First()
            from y in f(xss.Skip(1))
            select x + y;
        return query;
    }
};

var input = new []
{
    new [] { 1, 2, 3, 4, },
    new [] { 6, 7, 5, 2, 1, },
    new [] { 22, 4, 6, 8, 4, 8, 5, 4, },
};

var results = f(input);
like image 140
Enigmativity Avatar answered Oct 20 '22 08:10

Enigmativity


I think the linq version looks awesome:

from i in a
from j in b
from k in c
from m in d
select String.Join(",", i, j, k, m)

But the answer to your question is not easy. Eric Lippert wrote about it on his blog:

http://blogs.msdn.com/b/ericlippert/archive/2010/06/28/computing-a-cartesian-product-with-linq.aspx

like image 24
Dennis_E Avatar answered Oct 20 '22 09:10

Dennis_E