Return the cross product of a list of lists

后端 未结 4 2239
攒了一身酷
攒了一身酷 2021-01-17 09:06

Given a list of size n, Write a program that returns all possible combination of elements contained in each list.

Example:

  • List A = \"x, z\"
4条回答
  •  南方客
    南方客 (楼主)
    2021-01-17 09:32

    Think of it like how you increment a number, e.g. a base 3 number would go:

    000
    001
    002
    010
    011
    ...
    222
    

    Now think of each digit being the index into each of the nested lists. You will have as many digits as you have nested lists, i.e. the size of the outer list.

    The "base" of each digit may differ, and is the size of the corresponding nested list. A "digit" can be a very large number if a nested list is large.

    So, you start by creating a list of "digit", or index values, initializing them to 0. You then print the values of the elements at those indices. You then increment the last index value, rolling over as needed, like you would a normal number, stopping when the first index value rolls over.

    Here is a Java implementation using arrays of arrays, i.e. String[][]. You can easily change to List> or List if needed.

    @SafeVarargs
    public static void printCombos(String[] ... lists) {
        if (lists.length == 0)
            throw new IllegalArgumentException("No lists given");
        for (String[] list : lists)
            if (list.length == 0)
                throw new IllegalArgumentException("List is empty");
    
        int[] idx = new int[lists.length];
        for (;;) {
            // Print combo
            for (int i = 0; i < lists.length; i++) {
                if (i != 0)
                    System.out.print(' ');
                System.out.print(lists[i][idx[i]]);
            }
            System.out.println();
    
            // Advance to next combination
            for (int i = lists.length - 1; ++idx[i] == lists[i].length; ) {
                idx[i] = 0;
                if (--i < 0)
                    return; // We're done
            }
        }
    }
    
    public static void main(String[] args) {
        String[][] data = { { "x", "z" }, { "a", "b", "c" }, { "o", "p" } };
        printCombos(data);
    }
    

    OUTPUT

    x a o
    x a p
    x b o
    x b p
    x c o
    x c p
    z a o
    z a p
    z b o
    z b p
    z c o
    z c p
    

    If you use lists instead of arrays, then the code will use get(int), which may not always be good for performance, e.g. for LinkedList.

    If that is the case, replace int[] idx with an Iterator[], initializing each array entry with an iterator for the corresponding list. Resetting a "digit" to 0 would then be done by retrieving a new Iterator from the list in question.

    In this case, they don't even have to be lists, but can be any kind of collection, or more specifically Iterable objects.

提交回复
热议问题