Lets say I have two list ['a', 'b', 'c', 'd']
and ['x', 'y', 'z', 'w']
. I want to create a set of two other list where k elements are being exchanged between the two lists:
Example for a single element:
['x', 'b', 'c', 'd'] ['a', 'y', 'z', 'w']
['a', 'x', 'c', 'd'] ['b', 'y', 'z', 'w']
['a', 'b', 'x', 'd'] ['c', 'y', 'z', 'w']
['a', 'b', 'c', 'x'] ['d', 'y', 'z', 'w']
['y', 'b', 'c', 'd'] ['x', 'a', 'z', 'w']
['a', 'y', 'c', 'd'] ['x', 'b', 'z', 'w']
['a', 'b', 'y', 'd'] ['x', 'c', 'z', 'w']
['a', 'b', 'c', 'y'] ['x', 'd', 'z', 'w']
['z', 'b', 'c', 'd'] ['x', 'y', 'a', 'w']
['a', 'z', 'c', 'd'] ['x', 'y', 'b', 'w']
['a', 'b', 'z', 'd'] ['x', 'y', 'c', 'w']
['a', 'b', 'c', 'z'] ['x', 'y', 'd', 'w']
['w', 'b', 'c', 'd'] ['x', 'y', 'z', 'a']
['a', 'w', 'c', 'd'] ['x', 'y', 'z', 'b']
['a', 'b', 'w', 'd'] ['x', 'y', 'z', 'c']
['a', 'b', 'c', 'w'] ['x', 'y', 'z', 'd']
Is there an efficient way to generate this kind of lists?
The only thing I can think of is swapping elements in a for loop:
list_0 = ['a', 'b', 'c', 'd']
list_1 = ['x', 'y', 'z', 'w']
for j in range(len(list_0)):
for i in range(len(list_1)):
list_0[i], list_1[j] = list_1[j], list_0[i]
print(list_0, list_1)
list_0 = ['a', 'b', 'c', 'd']
list_1 = ['x', 'y', 'z', 'w']
This approach is very inefficient and am not sure how I could extend it to swapping k-elements.
I think the nested loops is as efficient as it gets, because you're basically generating a list of [source_index, target_index]
pairs. Though re-creating the lists on every iteration is indeed wasteful.
Here's a more straightforward solution for k=1, using itertools.product:
import itertools
list_0 = ['a', 'b', 'c', 'd']
list_1 = ['x', 'y', 'z', 'w']
indexes = range(len(list_0))
for j, i in itertools.product(indexes, repeat=2):
# Swap items.
list_0[i], list_1[j] = list_1[j], list_0[i]
print(list_0, list_1)
# Swap back.
list_0[i], list_1[j] = list_1[j], list_0[i]
# Alternative without swapping, by creating new lists.
# new_list_0 = [value if index != i else list_1[j] for index, value in enumerate(list_0)]
# new_list_1 = [value if index != j else list_0[i] for index, value in enumerate(list_1)]
# print(new_list_0, new_list_1)
# ['x', 'b', 'c', 'd'] ['a', 'y', 'z', 'w']
# ['a', 'x', 'c', 'd'] ['b', 'y', 'z', 'w']
# ['a', 'b', 'x', 'd'] ['c', 'y', 'z', 'w']
# ['a', 'b', 'c', 'x'] ['d', 'y', 'z', 'w']
# ['y', 'b', 'c', 'd'] ['x', 'a', 'z', 'w']
# ['a', 'y', 'c', 'd'] ['x', 'b', 'z', 'w']
# ['a', 'b', 'y', 'd'] ['x', 'c', 'z', 'w']
# ['a', 'b', 'c', 'y'] ['x', 'd', 'z', 'w']
# ['z', 'b', 'c', 'd'] ['x', 'y', 'a', 'w']
# ['a', 'z', 'c', 'd'] ['x', 'y', 'b', 'w']
# ['a', 'b', 'z', 'd'] ['x', 'y', 'c', 'w']
# ['a', 'b', 'c', 'z'] ['x', 'y', 'd', 'w']
# ['w', 'b', 'c', 'd'] ['x', 'y', 'z', 'a']
# ['a', 'w', 'c', 'd'] ['x', 'y', 'z', 'b']
# ['a', 'b', 'w', 'd'] ['x', 'y', 'z', 'c']
# ['a', 'b', 'c', 'w'] ['x', 'y', 'z', 'd']
And here's a general solution for any k
:
import itertools
list_0 = ['a', 'b', 'c', 'd']
list_1 = ['x', 'y', 'z', 'w']
k = 2 # Number of elements to swap.
indexes = range(len(list_0))
for source_indexes in itertools.permutations(indexes, k):
for target_indexes in itertools.combinations(indexes, k):
# Swap elements.
for target_index, source_index in zip(source_indexes, target_indexes):
list_0[source_index], list_1[target_index] = list_1[target_index], list_0[source_index]
print(list_0, list_1)
# Swap back.
for target_index, source_index in zip(source_indexes, target_indexes):
list_0[source_index], list_1[target_index] = list_1[target_index], list_0[source_index]
# ['x', 'y', 'c', 'd'] ['a', 'b', 'z', 'w']
# ['x', 'b', 'y', 'd'] ['a', 'c', 'z', 'w']
# ['x', 'b', 'c', 'y'] ['a', 'd', 'z', 'w']
# ['a', 'x', 'y', 'd'] ['b', 'c', 'z', 'w']
# ['a', 'x', 'c', 'y'] ['b', 'd', 'z', 'w']
# ['a', 'b', 'x', 'y'] ['c', 'd', 'z', 'w']
# ['x', 'z', 'c', 'd'] ['a', 'y', 'b', 'w']
# ['x', 'b', 'z', 'd'] ['a', 'y', 'c', 'w']
# ['x', 'b', 'c', 'z'] ['a', 'y', 'd', 'w']
# ['a', 'x', 'z', 'd'] ['b', 'y', 'c', 'w']
# ['a', 'x', 'c', 'z'] ['b', 'y', 'd', 'w']
# ['a', 'b', 'x', 'z'] ['c', 'y', 'd', 'w']
# ['x', 'w', 'c', 'd'] ['a', 'y', 'z', 'b']
# ['x', 'b', 'w', 'd'] ['a', 'y', 'z', 'c']
# ['x', 'b', 'c', 'w'] ['a', 'y', 'z', 'd']
# ['a', 'x', 'w', 'd'] ['b', 'y', 'z', 'c']
# ['a', 'x', 'c', 'w'] ['b', 'y', 'z', 'd']
# ['a', 'b', 'x', 'w'] ['c', 'y', 'z', 'd']
# ['y', 'x', 'c', 'd'] ['b', 'a', 'z', 'w']
# ...