skiwi
skiwi

Reputation: 69259

Return a list of combinations

I have made the functions already, but I'm stuck currently with the implementation. It is especially hard to think about it when it involves multiple variables.

What I want: With input [["A", "B"], ["0", "1", "2"]], I want as output [["A", "0"], ["A", "1"], ["A", "2"], ["B", "0"], ["B", "1"], ["B", "2"]]. I hope that is clear enough.

My code until now:

/**
 * Returns a list of all possible combinations of the entered lists.
 *
 * Example: [["A", "B"], ["0", "1", "2"]]
 * Returns: [["A", "0"], ["A", "1"], ["A", "2"], ["B", "0"], ["B", "1"], ["B", "2"]]
 *
 * @param <T> The type parameter
 * @param elements An array of lists
 * @return All possible combinations of the entered lists
 */
public static <T> List<List<T>> createCombinations(List<T>... elements) {
    int[] i = new int[elements.length];
    List<List<T>> returnLists = new ArrayList<>();

    for (int j = 0; j < elements.length; j++) {

    }

    return returnLists;
}

public static <T> List<List<T>> createCombinations(List<List<T>> elements) {
    return createCombinations((List<T>[])elements.toArray());
}

EDIT: It may be a bit confusing on how I actually want to use it, but this is how:
List<List<String>> combinations = Utils.createCombinations(cocNumbers, vatNumbers, ibans);.

Upvotes: 0

Views: 155

Answers (3)

BambooleanLogic
BambooleanLogic

Reputation: 8161

A simple way to do this is a recursive approach. Have the method do a for loop for the first list to go through all its values. Each time it picks one, it calls itself with the first list removed. It then adds the value it picked to the recursive call's return value. Return a list of all these values created by the for loop.

Pseudocode:

public static <T> List<List<T>> createCombinations(List<T>... elements) {
    (call non-vararg function)
}

public static <T> List<List<T>> createCombinations(List<List<T>> elements) {
    if (elements is empty) {
        return empty list
    } 
    List<T> head = get first list in elements
    List<T> tail = everything in elements except the first list
    List<T> allCombinations = empty list
    List<T> subcombinations = createCombinations(tail);
    for(every value in head) {
        List<T> x = copy of subcombinations with current value added to front
        add x to allCombinations
    }
    retyrn allCombinations;
}

Upvotes: 2

skiwi
skiwi

Reputation: 69259

Figured it out myself eventually.

The code itself:

/**
 * Returns a list of all possible combinations of the entered array of lists.
 *
 * Example: [["A", "B"], ["0", "1", "2"]]
 * Returns: [["A", "0"], ["A", "1"], ["A", "2"], ["B", "0"], ["B", "1"], ["B", "2"]]
 *
 * @param <T> The type parameter
 * @param elements An array of lists
 * @return All possible combinations of the entered lists
 */
public static <T> List<List<T>> createCombinations(List<T>... elements) {
    List<List<T>> returnLists = new ArrayList<>();

    int[] indices = new int[elements.length];
    for (int i = 0; i < indices.length; i++) {
        indices[i] = 0;
    }

    returnLists.add(generateCombination(indices, elements));
    while (returnLists.size() < countCombinations(elements)) {
        gotoNextIndex(indices, elements);
        returnLists.add(generateCombination(indices, elements));
    }

    return returnLists;
}

/**
 * Jumps to the next index for creating combinations.
 *
 * This method updates the indices.
 *
 * @param <T> The type parameter
 * @param indices The index positions
 * @param elements Array of lists
 */
private static <T> void gotoNextIndex(int[] indices, List<T>... elements) {
    for (int j = indices.length - 1; j >= 0; j--) {
        if (indices[j] == elements[j].size() - 1) {
            indices[j] = 0;
            continue;
        }
        indices[j]++;
        return;
    }
}

/**
 * Return a combination in the form of a list based on the current indices.
 *
 * @param <T> The type parameter
 * @param indices The index positions
 * @param elements Array of lists
 * @return The combination
 */
private static <T> List<T> generateCombination(int[] indices, List<T>... elements) {
    List<T> returnList = new ArrayList<>();
    for (int i = 0; i < indices.length; i++) {
        returnList.add(elements[i].get(indices[i]));
    }
    return returnList;
}

/**
 * Counts the possible number of combinations in this array of lists.
 *
 * @param <T> The type parameter
 * @param elements Array of lists
 * @return Possible number of combinations
 */
private static <T> int countCombinations(List<T>... elements) {
    int count = 1;
    for (List<T> list : elements) {
        count *= list.size();
    }
    return count;
}

/**
 * Returns a list of all possible combinations of the entered list of lists.
 *
 * Example: [["A", "B"], ["0", "1", "2"]]
 * Returns: [["A", "0"], ["A", "1"], ["A", "2"], ["B", "0"], ["B", "1"], ["B", "2"]]
 *
 * @param <T> The type parameter
 * @param elements A list of lists
 * @return All possible combinations of the entered lists
 */
public static <T> List<List<T>> createCombinations(List<List<T>> elements) {
    return createCombinations((List<T>[])elements.toArray());
}

Example:

List<String> l1 = new ArrayList<>();
l1.add("A");
l1.add("B");
List<String> l2 = new ArrayList<>();
l2.add("0");
l2.add("1");
l2.add("2");
List<String> l3 = new ArrayList<>();
l3.add("w");
l3.add("x");
l3.add("y");
l3.add("z");
List<List<String>> combs = Utils.createCombinations(l1, l2, l3);
for (List<String> l : combs) {
    System.out.println("l = " + l);
}

Example output:

l = [A, 0, w]
l = [A, 0, x]
l = [A, 0, y]
l = [A, 0, z]
l = [A, 1, w]
l = [A, 1, x]
l = [A, 1, y]
l = [A, 1, z]
l = [A, 2, w]
l = [A, 2, x]
l = [A, 2, y]
l = [A, 2, z]
l = [B, 0, w]
l = [B, 0, x]
l = [B, 0, y]
l = [B, 0, z]
l = [B, 1, w]
l = [B, 1, x]
l = [B, 1, y]
l = [B, 1, z]
l = [B, 2, w]
l = [B, 2, x]
l = [B, 2, y]
l = [B, 2, z]

Upvotes: 0

Teresa Carrigan
Teresa Carrigan

Reputation: 698

Use a for loop inside a for loop. The outer loop iterates through the array for the first element in each of your combinations, and the inner loop iterates through the other array.

Upvotes: 0

Related Questions