-1

I'm trying to get all possible combinations from a 2D array, let's say that I have an array full of numbers;

int[][] Values = new int[][] {{1, 2}, {3, 4}};

What I want is combinations like this:

[1-2], [2-1], [3-2], [2-3], [3-3], [2-2], [1-3], [1-1]

Basically the same number can get used over and over again, but I don't want to get the same combination in them. I hope I could explain what I'm trying to do. I couldn't find other answers that did what I wanted.

Edit:

I tried the answers from All possible combinations of a 2D array too but it didn't work, this question doesn't have anything to do with that question. I want arrays with numbers that can be used again, I don't want numbers to be unique.

MrEAZL
  • 3
  • 2

1 Answers1

1

You are looking for Cartesian Join. Given jagged array (int[][] is jagged array, not 2D one)

  int[][] Values = new int[][] { 
    new int[] { 1, 2 }, 
    new int[] { 3, 4 }, 
  };

You can Join it with itself as

  var result = Values
    .SelectMany(line => line)              // flatten
    .Join(Values.SelectMany(line => line), // flatten
          x => true,                       
          y => true,                        
         (x, y) => new int[] { x, y });

In case of 2D array int [,]

  int[,] Values = new int[,] { 
    { 1, 2 }, 
    { 3, 4 }, 
  };

you can use the same idea, but with OfType instead of SelectMany:

  var result = Values
    .OfType<int>()              // flatten
    .Join(Values.OfType<int>(), // flatten
          x => true,                       
          y => true,                        
         (x, y) => new int[] { x, y });

Let's have a look:

  Console.Write(string.Join(Environment.NewLine, result
    .Select(line => $"[{string.Join(", ", line)}]")));

Outcome:

[1, 1]
[1, 2]
[1, 3]
[1, 4]
[2, 1]
[2, 2]
[2, 3]
[2, 4]
[3, 1]
[3, 2]
[3, 3]
[3, 4]
[4, 1]
[4, 2]
[4, 3]
[4, 4]

Edit: To get all combinations of 3 items (i.e. {1, 1, 1}, {1, 1, 2} .. {4, 4, 4}) you can add one more Join. For jagged array [,] it can be

  var result = Values
    .SelectMany(line => line)              // flatten
    .Join(Values.SelectMany(line => line), // flatten
       x => true,
       y => true,
       (x, y) => (a: x, b: y))
    .Join(Values.SelectMany(line => line), // flatten
       x => true,
       y => true,
       (x, y) => new int[] {x.a, x.b, y});

To get all 4 items combinations you can add yet another Join, etc.:

  var result = Values
    .SelectMany(line => line)              // flatten
    .Join(Values.SelectMany(line => line), // flatten
       x => true,
       y => true,
       (x, y) => (a: x, b: y))
    .Join(Values.SelectMany(line => line), // flatten
       x => true,
       y => true,
       (x, y) => (a: x.a, b: x.b, c: y))
    .Join(Values.SelectMany(line => line), // flatten
       x => true,
       y => true,
       (x, y) => new int[] {x.a, x.b, x.c, y});
Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
  • Is there a way to make it change how many numbers are in one combination depending on the count of how many arrays are in the 2D array? – MrEAZL Nov 19 '21 at 15:41
  • @MrEAZL: if you want to find out combinations of `3` items i.e. `{1, 1, 1}, {1, 1, 2}, {1, 1, 3} .. {4, 4, 4}` you should use nested `Join`s: find combinations of `2` items add one more `Join` to get all combiations of `3` items – Dmitry Bychenko Nov 19 '21 at 15:48
  • I'm pretty new to those stuff in C# and I don't know how to do it, I would be really happy if you can edit your post and put an example or something. – MrEAZL Nov 19 '21 at 15:52
  • @MrEAZL: I've edited the answer, I add a code to get all 3 item cmbinations – Dmitry Bychenko Nov 19 '21 at 16:06