2 Stimmen

Python: Erstellen möglicher Unterlisten aus 2 Listen, bei denen die Reihenfolge nicht geändert wird

Ich habe 2 Listen und muss verschiedene Unterlisten erstellen, in denen die Reihenfolge nicht wieder verwendet werden soll (siehe Beispiel zur Verdeutlichung)

list1= [ a, b, c, d]
list2= [A, B, C, D]

Ich brauche alle möglichen Unterlisten wie

[a, B,C,D], [ a,b, C, D], [A,B,c,d], [a,b,c,D] ... es gibt 2 pow 4 = 16 Lösungen [Suche nach 2 pow N Lösung]

Ich danke Ihnen im Voraus

3voto

Sujoy Gupta Punkte 1414
list1 = ['a', 'b', 'c', 'd']
list2 = ['A', 'B', 'C', 'D']

for i in xrange(2**len(list1)):
    output = []
    for j in xrange(0, len(list1)):
        bit = i & (1 << j)
        if bit == 0:
            output.append(list1[j])
        else:
            output.append(list2[j])
    print output

2voto

Lauritz V. Thaulow Punkte 45363

Ich habe das Gefühl, dass man es besser machen kann, aber so funktioniert es zumindest:

from itertools import product
a = "abcd"
A = "ABCD"
print [[a[y] if x[y] else A[y] for y in range(len(x))] \
    for x in product(range(2), repeat=4)]

EDIT: Ein alternativer Weg:

lists = ["abcd", "ABCD"]
print [[lists[y][i] for i, y in enumerate(x)] \
    for x in product(range(2), repeat=4)]

EDIT 2: Eine generische Lösung für eine beliebige Anzahl von Listen:

def sublist(*lists):
    if not len(set(len(x) for x in lists)) == 1:
        raise ValueError("Lists must all be the same length")
    length = len(lists[0])
    return [[lists[y][i] for i, y in enumerate(x)] \
        for x in product(range(len(lists)), repeat=length)]

print sublist("ab", "AB", "12")
# [['a', 'b'], ['a', 'B'], ['a', '2'], ['A', 'b'], ['A', 'B'], ['A', '2'], ['1', 'b'], ['1', 'B'], ['1', '2']]

1voto

Ist die Rekursion Ihr Freund:

def sublists(l1, l2):
    if not l1:
        return [l1]
    sl = sublists(l1[1:], l2[1:])
    return [l1[:1] + l for l in sl] + [l2[:1] + l for l in sl]

Oder, wenn Sie Generatoren mögen:

def subgen(l1, l2):
    if not l1:
        yield l1
        return
    for sl in subgen(l1[1:], l2[1:]):
        yield l1[:1] + sl
        yield l2[:1] + sl

0voto

tokland Punkte 63238
import itertools
[[(y if selector else x) for (selector, x, y) in zip(lidxs, list1, list2)]  
 for lidxs in itertools.product([0, 1], repeat=4)]

[['a', 'b', 'c', 'd'],
 ['a', 'b', 'c', 'D'],
 ['a', 'b', 'C', 'd'],
 ...
 ['A', 'B', 'c', 'D'],
 ['A', 'B', 'C', 'd'],
 ['A', 'B', 'C', 'D']]

Auch:

[[[list1, list2][lidx][i] for (i, lidx) in enumerate(lidxs)] 
 for lidxs in itertools.product([0, 1], repeat=4)]]

Ersetzen Sie [...] durch (...), um einen trägen Generator zu erhalten. Wenn Sie die (etwas) ausführlichere Ausbeute anstelle von Einzeilern bevorzugen, kann sie leicht umgewandelt werden. Zum Beispiel das zweite Beispiel, verallgemeinert:

def generate_sublists(*lsts):
    for lidxs in itertools.product(range(len(lsts)), repeat=len(lsts[0])):
        yield [lsts[lidx][i] for (i, lidx) in enumerate(lidxs)]

0voto

pillmuncher Punkte 9804
from itertools import imap, product

a = "abcd"
A = "ABCD"

print [[[a,A][i][j] for j,i in each] for each in imap(enumerate, product((0, 1), repeat=4))]

[Bearbeiten]

Aber das hier ist besser, IMO:

from itertools import izip, product

a = 'abcd'
A = 'ABCD'

choices = zip(a, A)

print [[c[i] for c, i in izip(choices, p)] for p in product((0, 1), repeat=4)]

Auch das funktioniert:

from functools import partial
from itertools import product

a = 'abcd'
A = 'ABCD'

mapped = partial(map, tuple.__getitem__, zip(a, A))
print [mapped(p) for p in product((0, 1), repeat=4)]

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X