How to generate all permutations of the flattened list of lists in Python, ... such that the order in the lists is maintained?
Example;
input;
[[1,2], [3]]
output;
[1,2,3]
[1,3,2]
[3,1,2]
1 is always before 2 in the permutations.
How to generate all permutations of the flattened list of lists in Python, ... such that the order in the lists is maintained?
Example;
input;
[[1,2], [3]]
output;
[1,2,3]
[1,3,2]
[3,1,2]
1 is always before 2 in the permutations.
IIUC, you could model this as finding all topological sorts in a DAG, so I suggest you use networkx, for example:
import itertools
import networkx as nx
data = [[1,2], [3]]
edges = [edge for ls in data for edge in zip(ls, ls[1:])]
# this creates a graph from the edges (e.g. [1, 2])
dg = nx.DiGraph(edges)
# add all the posible nodes (e.g. {1, 2, 3})
dg.add_nodes_from(set(itertools.chain.from_iterable(data)))
print(list(nx.all_topological_sorts(dg)))
Output
[[3, 1, 2], [1, 2, 3], [1, 3, 2]]
For the input provided, the following DiGraph is created:
Nodes: [1, 2, 3], Edges: [(1, 2)]
A topological sorting imposes the constraint that 1
is always going to be present before 2
. More on all topological sortings can be found, here.
Interesting problem; I'm not sure whether there is a builtin in itertools for this, but this would seem to work:
l = [[1,2], [3]]
# Create list containing indexes of sublists by the number of elements in that
# sublist - in this case [0, 0, 1]
l2 = [y for i, x in enumerate(l) for y in [i]*len(x)]
rv = []
# For every unique permutation of l2:
for x in set(itertools.permutations(l2)):
l = [[1,2], [3]]
perm = []
# Create a permutation from l popping the first item of a sublist when
# we come across that sublist's index
for i in x:
perm.append(l[i].pop(0))
rv.append(tuple(perm))
>>> rv
[(3, 1, 2), (1, 3, 2), (1, 2, 3)]
Starting from the permutations generator, filter by checking that all input sublists are sublists of the permutations. Sublist function from here.
l = [[1,2], [3]]
def sublist(lst1, lst2):
ls1 = [element for element in lst1 if element in lst2]
ls2 = [element for element in lst2 if element in lst1]
return ls1 == ls2
[perm for perm in itertools.permutations(itertools.chain.from_iterable(l))
if all(sublist(l_el, perm) for l_el in l)]
[(1, 2, 3), (1, 3, 2), (3, 1, 2)]