简体   繁体   中英

How to generate all permutations of the flattened list of lists?

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:

Code:

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))

Output:

>>> 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)]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM