So erhalten Sie das kartesische Produkt mehrerer Listen

Lesezeit: 6 Minuten

Benutzeravatar von ʞɔıu
ʞɔıu

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

Zum Beispiel gegeben

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

Wie bekomme ich das?

[(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.

Viele Leute, die es bereits wissen itertools.product hat damit zu kämpfen, dass es für jede Eingabesequenz separate Argumente erwartet und nicht zB eine Liste von Listen. Die akzeptierte Antwort zeigt, wie damit umzugehen ist *. Allerdings ist die Verwendung von * Hier zum Auspacken von Argumenten grundsätzlich nicht anders von jeder anderen Zeit wird es in einem Funktionsaufruf verwendet. Siehe Erweitern von Tupeln in Argumente für dieses Thema (und verwenden Sie das stattdessen, um doppelte Fragen zu schließen, falls erforderlich).

  • 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. Andererseits, 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

  • @Jaska: product() erzeugt nitems_in_a_list ** nlists Elemente im Ergebnis (reduce(mul, map(len, somelists))). Es gibt keinen Grund zu der Annahme, dass das Nachgeben eines einzelnen Elements dies nicht ist O(nlists) (amortisiert), dh der zeitliche Aufwand ist der gleiche wie bei einfach verschachtelt for-Schleifen z. B. für die Eingabe in der Frage: nlists=3Gesamtzahl der Elemente im Ergebnis: 3*2*2und jedes Element hat nlists Artikel (3 in diesem Fall).

    – jfs

    14. August 2015 um 22:08 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

  • Nur ein Detail, aber beachten Sie das itertools.product() kann auch mit Generatoren umgehen und nicht nur mit listenähnlichen Objekten.

    – Normanius

    5. Dezember 2018 um 23:18 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]]))

Ausgang:

[(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

1443430cookie-checkSo erhalten Sie das kartesische Produkt mehrerer Listen

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

Privacy policy