Any possible replacements for two lists?
(I know the title of the question can be misleading, but I couldn't find any other way to formulate it - feel free to edit it)
I have two lists with the same length:
a = [1,2,3]
b = [4,5,6]
And I want to get all possible replacements of the first list with the second list.
output[0] = [1,2,3] # no replacements
output[1] = [4,2,3] # first item was replaced
output[2] = [1,5,3] # second item was replaced
output[3] = [1,2,6] # third item was replaced
output[4] = [4,5,3] # first and second items were replaced
output[5] = [4,2,6] # first and third items were replaced
output[6] = [1,5,6] # second and third items were replaced
output[7] = [4,5,6] # all items were replaced
Please note that this question is NOT answered by the following questions:
- How do I get all the possible combinations of list items?
- combinations between two lists?
- Python concatenates two lists with all possible permutations
- All combinations of a list of lists
A possible solution related to the previously linked answers would be to create multiple lists and then use the itertools.product method. For example, instead of having 2 lists of 3 items, I could create 3 lists of 2 items; however, it would make the code too complex and I would rather avoid it if I could.
Is there an easy and quick way to do this?
source to share
Making 3 lists of 2 items won't over complicate your code at all. zip
can "flip axes" from multiple lists is trivial (making X-sequences of Y-elements into Y-sequences of X-elements), making it easy to use itertools.product
:
import itertools
a = [1,2,3]
b = [4,5,6]
# Unpacking result of zip(a, b) means you automatically pass
# (1, 4), (2, 5), (3, 6)
# as the arguments to itertools.product
output = list(itertools.product(*zip(a, b)))
print(*output, sep="\n")
What are the outputs:
(1, 2, 3) (1, 2, 6) (1, 5, 3) (1, 5, 6) (4, 2, 3) (4, 2, 6) (4, 5, 3) (4, 5, 6)
Different order, different from your example, but the same set of possible replacements.
source to share
Each element can be independently replaced or left alone. This can be modeled by a bit equal to 1 or 0. If you treat each element as a separate bit, then repeating all possible possibilities can be mapped to iterate over all combinations of n bits.
In other words, iterating from 0 to 2 n -1 and looking at bit patterns.
n = len(a)
for i in range(2**n):
yield [a[j] if i & (1 << j) != 0 else b[j] for j in range(n)]
Aborting this i & (1 << j) != 0
checks if the jth bit of i is set. If so, use a[j]
otherwise b[j]
.
Result:
[1, 2, 3]
[4, 2, 3]
[1, 5, 3]
[4, 5, 3]
[1, 2, 6]
[4, 2, 6]
[1, 5, 6]
[4, 5, 6]
source to share
Ok, this is similar to the other answers, but a bit from both of them. You can model your problem as finding all possible bits of a sequence of a given length and replacing only when there is 1, and not otherwise.
from itertools import product
a = [1,2,3]
b = [4,5,6]
## All binary combinations of length of a (or b)
combinations = product([0,1], repeat=len(a))
for combination in combinations:
y = []
for l, i in zip(zip(a,b),combination):
y.append(l[i])
print y
All bit combinations:
(0, 0, 0) (0, 0, 1) (0, 1, 0) (0, 1, 1) (1, 0, 0) (1, 0, 1) (1, 1, 0) (1, 1, 1)
Result:
[1, 2, 3]
[1, 2, 6]
[1, 5, 3]
[1, 5, 6]
[4, 2, 3]
[4, 2, 6]
[4, 5, 3]
[4, 5, 6]
source to share