Search code examples
javaarrayscombinationspermutation

How do I generate combinations of two arrays?


Given two arrays, where array one has variables and array two contains the variable's values, I want to get all possible combinations of those two arrays, for example:

String[] arr = {"E", "A", "C"};
String[] val = {"true", "false"};

Array arr can hold as many variables as possible, and val too.

Desired output:

E true A true C true
E true A true C false
E true A false C true
E true A false C false

E false A true C true
E false A true C false
E false A false C true
E false A false C false

I tried a recursion approach:

import java.util.*;

class Main {
    public static void main(String[] args) {
        String[] arr = {"E", "A", "C"};
        String[] val = {"true", "false"};
        printAll(arr, val, 0);
    }

    public static void printAll(String[] x, String[] y, int index) {
        if (x.length == 0) {
            return;
        }
        for (String d : x) {
            for (String val : y) {
                System.out.print(d + " " + val + " ");
                String[] arr2 = Arrays.copyOfRange(x, index + 1, x.length);
                printAll(arr2, y, index);
            }
        }
        System.out.println();
    }
}

But the output that I get is:

E true A true C true C false 
A false C true C false 
C true C true C false 
C false C true C false 

E false A true C true C false 
A false C true C false 
C true C true C false 
C false C true C false 

A true A true C true C false 
A false C true C false 
C true C true C false 
C false C true C false 

A false A true C true C false 
A false C true C false 
C true C true C false 
C false C true C false 

C true A true C true C false 
A false C true C false 
C true C true C false 
C false C true C false 

C false A true C true C false 
A false C true C false 
C true C true C false 
C false C true C false 

I want to be able to save each correct line as an element in an ArrayList but first I want to figure out how to print each line correctly.


EDIT: The second array is not constant, it differs between each variable:

String[] arr = {"E", "A", "C"};
String[] valE = {"true", "false"};
String[] valA = {"true", "false"};
String[] valB = {"set", "noset", "maybe"};

Obviously this wont work in recursion as I need to send each array along side the variables array, I achieve this by creating a Variables object which contains its specific values, so the loop would be:

for (String d : x) {
    for (String val : d.getValues()) {...}
}

This is not relevant to the main question, I simply reduced the question to a simple case where each variable has two possible values.


Solution

  • You can iteratively generate all possible combinations of two arrays using streams as follows:

    String[] arr = {"E", "A", "C"};
    String[] val = {"true", "false"};
    
    // an array of possible combinations
    String[] comb = Arrays.stream(arr)
            .map(e -> Arrays.stream(val)
                    // append each substring
                    // with possible combinations
                    .map(v -> e + " " + v + " ")
                    // return Stream<String[]>
                    .toArray(String[]::new))
            // reduce stream of arrays to a single array
            // by sequentially multiplying array pairs
            .reduce((arr1, arr2) -> Arrays.stream(arr1)
                    .flatMap(str1 -> Arrays.stream(arr2)
                            .map(str2 -> str1 + str2))
                    .toArray(String[]::new))
            .orElse(null);
    
    // output
    Arrays.stream(comb).forEach(System.out::println);
    
    E true A true C true 
    E true A true C false 
    E true A false C true 
    E true A false C false 
    E false A true C true 
    E false A true C false 
    E false A false C true 
    E false A false C false 
    

    See also: Generate all possible string combinations by replacing the hidden “#” number sign