Search code examples
pythoncombinationspermutation

List all combinations with replacement (but order matters) of all permutations of a list


Given an input list such as [1, 2], I'd like to obtain a list of combinations of all the possible permutations of the input list. So something like:

List of permutations: [[1, 2], [2, 1]]

List of combinations:

[[[1, 2], [1, 2]],
 [[1, 2], [2, 1]],
 [[2, 1], [1, 2]],
 [[2, 1], [2, 1]]]

Where the number of objects to choose is equal to the length of the original list (so 2 choices per combination)

I tried this using itertools:

def generate_preferences(input_list):
    n = len(input_list)
    all_permutations = [list(p) for p in list(permutations(input_list, n))]
    all_combinations = [list(p) for p in list(combinations_with_replacement(all_permutations, n))]
    return all_combinations

But got the following result back:

[[[1, 2], [1, 2]], [[1, 2], [2, 1]], [[2, 1], [2, 1]]]

And I'm not sure how to specify the order mattering, as my best guess is that the function is ignoring

[[1, 2], [2, 1]] vs [[2, 1], [1, 2]]


Solution

  • If order matters, you don't want combinations, you want the Cartesian product.

    Replace itertools.combinations_with_replacement with itertools.product:

    def generate_preferences(
        input_list: list[int]
    ) -> Iterator[tuple[tuple[int, ...], ...]]:
        n = len(input_list)
        all_permutations = itertools.permutations(input_list)
        return itertools.product(all_permutations, repeat=n)
    

    Then

    >>> list(generate_preferences([1, 2]))
    

    outputs

    [
        ((1, 2), (1, 2)), 
        ((1, 2), (2, 1)), 
        ((2, 1), (1, 2)), 
        ((2, 1), (2, 1)),
    ]