How do I generate combinations of two arrays?
Asked Answered
H

3

0

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.

Holoblastic answered 6/12, 2020 at 15:23 Comment(0)
V
1

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

Vandenberg answered 4/2, 2021 at 3:33 Comment(0)
A
2

You can generate a 2d array of possible combinations using map and reduce methods:

String[] array = {"E", "A", "C"};
String[] values = {"true", "false"};

String[][] combinations = Arrays.stream(array)
        // represent each string as a 2d array of possible combinations
        .map(str -> Arrays.stream(values).map(bool -> new String[]{str, bool})
                // stream of 2d arrays
                .toArray(String[][]::new))
        // intermediate output
        .peek(comb -> System.out.println(Arrays.deepToString(comb)))
        // reduce stream of 2d arrays to a single 2d array
        .reduce((arr1, arr2) -> Arrays.stream(arr1)
                // combinations of inner arrays
                .flatMap(inner1 -> Arrays.stream(arr2)
                        // merge two inner arrays into one
                        .map(inner2 -> Stream.of(inner1, inner2)
                                .flatMap(Arrays::stream)
                                .toArray(String[]::new)))
                // array of combinations
                .toArray(String[][]::new))
        // otherwise an empty 2d array
        .orElse(new String[0][]);

// final output
Arrays.stream(combinations).map(Arrays::toString).forEach(System.out::println);

Intermediate output:

[[E, true], [E, false]]
[[A, true], [A, false]]
[[C, true], [C, false]]

Final 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]

See also: Outputting permutations of ArrayList using recursion

Amaya answered 24/4, 2021 at 14:58 Comment(0)
V
1

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

Vandenberg answered 4/2, 2021 at 3:33 Comment(0)
A
0
import java.util.*;
public class Solution {

    public static String[] combineAllStrings(String[] s1, String[] s2) {
        int result =0;
        int N = s1.length*s2.length;
        String[] combineString= new String[N];
        for (int i=0;i<s1.length;i++){
            for (int j=0;j<s2.length;j++){
                combineString[result]=s1[i]+s2[j];
                System.out.println(combineString);
                result =result+1; 
            }
        }
        return combineString;
    }

    public static void main(String args[]) {

        String input1[] = {"a", "c", "e"};
        String input2[] = {"b", "d", "f"};
        String output[] = {"ab", "ad", "af", "cb", "cd", "cf", "eb", "ed", "ef"};
        assert Arrays.equals(combineAllStrings(input1, input2), output) : "Expect [\"ab\", \"ad\", \"af\", \"cb\", \"cd\", \"cf\", \"eb\", \"ed\", \"ef\"] for input1 = [\"a\", \"c\", \"e\"] and input2 = [\"b\", \"d\", \"f\"]";
        System.out.println("All test cases in main function passed");

    }
}
Anthropopathy answered 4/6, 2022 at 10:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.