So erhalten Sie das kartesische Produkt einer Reihe von Listen

Lesezeit: 5 Minuten

Benutzeravatar von ʞɔıu
ʞɔıu

Wie bekomme ich das kartesische Produkt (jede mögliche Kombination von Werten) aus einer Gruppe von Listen?

Eingang:

somelists = [
   [1, 2, 3],
   ['a', 'b'],
   [4, 5]
]

Gewünschte Ausgabe:

[(1, 'a', 4), (1, 'a', 5), (1, 'b', 4), (1, 'b', 5), (2, 'a', 4), (2, 'a', 5), ...]

Eine häufige Anwendung für diese Technik besteht darin, tief verschachtelte Schleifen zu vermeiden. Siehe Vermeidung von verschachtelten for-Schleifen für ein spezifischeres Duplikat.

Wenn Sie ein kartesisches Produkt von wollen das Gleiche Liste mehrfach mit sich selbst, itertools.product kann damit elegant umgehen. Siehe Operation für jedes Paar von Elementen in einer Liste oder Permutationen mit Wiederholungen generieren.

  • Beachten Sie, dass „jede mögliche Kombination“ nicht ganz dasselbe ist wie „kartesisches Produkt“, da bei kartesischen Produkten Duplikate zulässig sind.

    – Kenan-Banken

    10. Februar 2009 um 20:08 Uhr

  • Gibt es eine nicht duplizierte Version des kartesischen Produkts?

    – KJW

    13. November 2013 um 5:32 Uhr

  • @KJW Ja, set(cartesian product)

    – NoBugs

    12. Februar 2015 um 7:04 Uhr

  • In einem kartesischen Produkt sollten keine Duplikate vorhanden sein, es sei denn, die Eingabelisten enthalten selbst Duplikate. Wenn Sie keine Duplikate im kartesischen Produkt wünschen, verwenden Sie set(inputlist) über alle Ihre Eingabelisten. Nicht auf das Ergebnis.

    – CamilB

    24. August 2017 um 8:39 Uhr

  • Mathematisch gesehen ist ein kartesisches Produkt eine Menge, also ein kartesisches Produkt nicht Duplikate enthalten. Auf der anderen Seite, itertools.product hat Duplikate in der Ausgabe, wenn die Eingaben Duplikate haben. So itertools.product ist streng genommen nicht das kartesische Produkt, es sei denn, Sie packen die Eingaben ein setwie von @CamilB erwähnt.

    – Cameron Bieganek

    8. Dezember 2020 um 22:56 Uhr

Benutzeravatar von Kenan Banks
Kenan-Banken

Verwenden itertools.productdas seit Python 2.6 verfügbar ist.

import itertools

somelists = [
   [1, 2, 3],
   ['a', 'b'],
   [4, 5]
]
for element in itertools.product(*somelists):
    print(element)

Dies ist dasselbe wie:

for element in itertools.product([1, 2, 3], ['a', 'b'], [4, 5]):
    print(element)

  • Ich wollte nur das Zeichen „*“ hinzufügen, wenn Sie die vom OP bereitgestellte Variable somelists verwenden.

    – Brian Buck

    13. Januar 2011 um 22:51 Uhr

  • Wozu benutzt man * vor Somelists? Was tut es?

    – Vineet Kumar Doshi

    25. August 2015 um 9:04 Uhr

  • @VineetKumarDoshi: Hier wird es verwendet, um eine Liste in mehrere Argumente für den Funktionsaufruf zu entpacken. Lesen Sie hier mehr: stackoverflow.com/questions/36901/…

    – Möberg

    15. September 2015 um 6:20 Uhr

  • Hinweis: Dies funktioniert nur, wenn jede Liste mindestens ein Element enthält

    – ich gehe

    13. September 2017 um 12:35 Uhr

  • @igo funktioniert auch, wenn eine Liste null Elemente enthält – das kartesische Produkt von mindestens einer Liste der Größe null und allen anderen Listen ist eine leere Liste, und das ist genau das, was dies erzeugt.

    – Ruzihm

    9. Oktober 2019 um 20:42 Uhr

import itertools
>>> for i in itertools.product([1,2,3],['a','b'],[4,5]):
...         print i
...
(1, 'a', 4)
(1, 'a', 5)
(1, 'b', 4)
(1, 'b', 5)
(2, 'a', 4)
(2, 'a', 5)
(2, 'b', 4)
(2, 'b', 5)
(3, 'a', 4)
(3, 'a', 5)
(3, 'b', 4)
(3, 'b', 5)
>>>

Benutzeravatar von jfs
jfs

Für Python 2.5 und älter:

>>> [(a, b, c) for a in [1,2,3] for b in ['a','b'] for c in [4,5]]
[(1, 'a', 4), (1, 'a', 5), (1, 'b', 4), (1, 'b', 5), (2, 'a', 4), 
 (2, 'a', 5), (2, 'b', 4), (2, 'b', 5), (3, 'a', 4), (3, 'a', 5), 
 (3, 'b', 4), (3, 'b', 5)]

Hier ist eine rekursive Version von product() (nur eine Veranschaulichung):

def product(*args):
    if not args:
        return iter(((),)) # yield tuple()
    return (items + (item,) 
            for items in product(*args[:-1]) for item in args[-1])

Beispiel:

>>> list(product([1,2,3], ['a','b'], [4,5])) 
[(1, 'a', 4), (1, 'a', 5), (1, 'b', 4), (1, 'b', 5), (2, 'a', 4), 
 (2, 'a', 5), (2, 'b', 4), (2, 'b', 5), (3, 'a', 4), (3, 'a', 5), 
 (3, 'b', 4), (3, 'b', 5)]
>>> list(product([1,2,3]))
[(1,), (2,), (3,)]
>>> list(product([]))
[]
>>> list(product())
[()]

  • Die rekursive Version funktioniert nicht, wenn einige von args sind Iteratoren.

    – jfs

    10. Februar 2009 um 21:43 Uhr

Ich würde das Listenverständnis verwenden:

somelists = [
   [1, 2, 3],
   ['a', 'b'],
   [4, 5]
]

cart_prod = [(a,b,c) for a in somelists[0] for b in somelists[1] for c in somelists[2]]

Benutzeravatar von SilentGhost
SilentGhost

mit itertools.product:

import itertools
result = list(itertools.product(*somelists))

  • Wozu benutzt man * vor Somelists?

    – Vineet Kumar Doshi

    25. August 2015 um 9:04 Uhr

  • @VineetKumarDoshi “Produkt (einige Listen)” ist ein kartesisches Produkt zwischen den Unterlisten in einer Weise, die Python zuerst bekommt “[1, 2, 3]” als Element und erhält dann nach dem nächsten Befehl ein anderes Element, und das ist ein Zeilenumbruch, also ist der erste Produktbegriff ([1, 2, 3],), ähnlich für die zweite ([4, 5],) und so “[([1, 2, 3],), ([4, 5],), ([6, 7],)]”. Wenn Sie ein kartesisches Produkt zwischen Elementen innerhalb der Tupel erhalten möchten, müssen Sie Python mit Asterisk über die Tupelstruktur informieren. Für das Wörterbuch verwenden Sie **. Mehr hier.

    – hhh

    15. Februar 2016 um 23:13 Uhr

Benutzeravatar von Anurag Uniyal
Anurag Uniyal

Hier ist ein rekursiver Generator, der keine temporären Listen speichert

def product(ar_list):
    if not ar_list:
        yield ()
    else:
        for a in ar_list[0]:
            for prod in product(ar_list[1:]):
                yield (a,)+prod

print list(product([[1,2],[3,4],[5,6]]))

Ausgabe:

[(1, 3, 5), (1, 3, 6), (1, 4, 5), (1, 4, 6), (2, 3, 5), (2, 3, 6), (2, 4, 5), (2, 4, 6)]

  • Wozu benutzt man * vor Somelists?

    – Vineet Kumar Doshi

    25. August 2015 um 9:04 Uhr

  • @VineetKumarDoshi “Produkt (einige Listen)” ist ein kartesisches Produkt zwischen den Unterlisten in einer Weise, die Python zuerst bekommt “[1, 2, 3]” als Element und erhält dann nach dem nächsten Befehl ein anderes Element, und das ist ein Zeilenumbruch, also ist der erste Produktbegriff ([1, 2, 3],), ähnlich für die zweite ([4, 5],) und so “[([1, 2, 3],), ([4, 5],), ([6, 7],)]”. Wenn Sie ein kartesisches Produkt zwischen Elementen innerhalb der Tupel erhalten möchten, müssen Sie Python mit Asterisk über die Tupelstruktur informieren. Für das Wörterbuch verwenden Sie **. Mehr hier.

    – hhh

    15. Februar 2016 um 23:13 Uhr

In Python 2.6 und höher können Sie ‘itertools.product’ verwenden. In älteren Versionen von Python können Sie das folgende (fast — siehe Dokumentation) Äquivalent verwenden Code aus der Dokumentationzumindest als Ausgangspunkt:

def product(*args, **kwds):
    # product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy
    # product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111
    pools = map(tuple, args) * kwds.get('repeat', 1)
    result = [[]]
    for pool in pools:
        result = [x+[y] for x in result for y in pool]
    for prod in result:
        yield tuple(prod)

Das Ergebnis von beiden ist ein Iterator, wenn Sie also wirklich eine Liste zur weiteren Verarbeitung benötigen, verwenden Sie list(result).

  • Gemäß der Dokumentation erstellt die tatsächliche itertools.product-Implementierung KEINE Zwischenergebnisse, die teuer sein könnten. Die Verwendung dieser Technik könnte bei mittelgroßen Listen ziemlich schnell außer Kontrolle geraten.

    – Kenan-Banken

    10. Februar 2009 um 20:05 Uhr

  • Ich kann das OP nur auf die Dokumentation verweisen, sie nicht für ihn lesen.

    Benutzer3850

    10. Februar 2009 um 20:19 Uhr

  • Der Code aus der Dokumentation soll zeigen, was die Produktfunktion tut, und nicht als Problemumgehung für frühere Versionen von Python.

    – Kenan-Banken

    10. März 2009 um 21:07 Uhr

1436510cookie-checkSo erhalten Sie das kartesische Produkt einer Reihe von Listen

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy