Elsa Elsa - 9 days ago 5
Java Question

How to iterate using a specific order

I have a method where you can specify a list of parameters (test1, test2... ) and a list of lists with valid values that belongs to the previous parameters. How can I iterate through all values if I want to follow an specific order for given parameters?

String test1 = "parameter1";
String test2 = "parameter2";
String test3 = "parameter3";
List<String> validValuesforTest1 = Arrays.asList(new String[] { "test1", "test11" });
List<String> validValuesforTest2 = Arrays.asList(new String[] { "test2" });
List<String> validValuesforTest3 = Arrays.asList(new String[] { "test3", "test33", "test33" });


Expected behaviour:

for (String x : validValuesforTest1) {
for (String y : validValuesforTest2) {
for (String z : validValuesforTest3) {
return String.format("%s = %s, %s = %s, %s = %s", test1, x, test2, y, test3, z);
}
}
}


Where I don't know how many parameters are given.

Answer

This would be natural to implement using recursion. Write a method that takes a list of lists of the valid values, another list of the parameters, and a prefix string. The first and the second list must have the same length.

The recursion should terminate when the first list is empty, and print the value of the prefix.

Otherwise (the list is not empty), iterate over the elements of the first sublist, prepare the prefix for the recursive call, and then perform the recursive call with the tails of the two lists (without the head elements).

Something like this:

private void combine(List<List<String>> lists, List<String> params, StringBuilder prefix) {
    if (lists.isEmpty()) {
        System.out.println(prefix);
        return;
    }
    for (String value : lists.get(0)) {
        StringBuilder copy = new StringBuilder(prefix);
        if (copy.length() > 0) {
            copy.append(", ");
        }
        copy.append(params.get(0)).append(" = ").append(value);
        combine(lists.subList(1, lists.size()), params.subList(1, params.size()), copy);
    }
}

With your example input, you can call it like this:

public void demo() {
    String test1 = "parameter1";
    String test2 = "parameter2";
    String test3 = "parameter3";
    List<String> validValuesforTest1 = Arrays.asList(new String[] { "test1", "test11" });
    List<String> validValuesforTest2 = Arrays.asList(new String[] { "test2" });
    List<String> validValuesforTest3 = Arrays.asList(new String[] { "test3", "test33", "test33" });

    combine(
        Arrays.asList(validValuesforTest1, validValuesforTest2, validValuesforTest3),
        Arrays.asList(test1, test2, test3),
        new StringBuilder());
}

To get output:

parameter1 = test1, parameter2 = test2, parameter3 = test3
parameter1 = test1, parameter2 = test2, parameter3 = test33
parameter1 = test1, parameter2 = test2, parameter3 = test33
parameter1 = test11, parameter2 = test2, parameter3 = test3
parameter1 = test11, parameter2 = test2, parameter3 = test33
parameter1 = test11, parameter2 = test2, parameter3 = test33