Komplexer Vergleich von zwei Listen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
chrism_iller

Hallo Pythonier!,

ich bin Nachwuchs-Programmierer und benötige Hilfe bei folgendem Vorhaben.

Ich möchte zwei Listen auf bestimmte Kriterien miteinander vergleichen, wobei Liste2 zu nächst eine Kopie von Liste1 ist.

Liste1 = ["Apfel", "Banane", "Birne", "Traube", "Kirsche", "Melone"]
Liste2 = ["Apfel", "Banane", "Birne", "Traube", "Kirsche", "Melone"]

Nun mische ich Liste2 mit random.shuffle(Liste2), sodass ich bspw. Folgendes erhalte:

Liste1 = ["Apfel", "Banane", "Birne", "Traube", "Kirsche", "Melone"]
Liste2 = ["Birne", "Melone", "Traube", "Apfel", "Kirsche", "Banane"]

Ich möchte nun (am besten mittels einer Schleife) prüfen, ob die jeweiligen Strings (an gleicher Position) der Listen übereinstimmen.
Also in Pseudocode:
Liste1[0] == Liste2[0] ?
Liste1[1] == Liste2[1] ?
... == ... ?

Wird nun eine Übereinstimmung gefunden, also wenn z.B. Liste1[4] == "Kirsche" und Liste2[4] == "Kirsche" ist,
soll Liste2 erneut gemischt werden und das Prozedere beginnt von Neuem (wieder bei Liste1[0] == Liste2[0]).

Das Programm soll solange laufen, bis jedem Obst ein anderes Obst zugeordnet ist.
Ich habe hier Probleme, n Wiederholungen durchführen zu lassen, bis meine Bedingung (alles ist ungleich) eintritt.

Vielen Dank im Voraus! :)
__deets__
User
Beiträge: 14523
Registriert: Mittwoch 14. Oktober 2015, 14:29

Mit zip kannst du über beide Listen gleichzeitig laufen. Mit any kannst du prüfen, ob auch nur eines der Paare gleich ist. Und schon hast du dein Prädikat.

Code: Alles auswählen

any(a == b for a, b in zip(l1, l2))
Wobei man wahrscheinlich auch effizienter vorgehen kann, und statt die Liste zu shufflen einfach für jede Stelle zufällig eine neue bestimmt, die nicht die alte sein darf.
Caskuda
User
Beiträge: 26
Registriert: Sonntag 15. März 2020, 22:09

Wie genau sehen denn die Eingangs-Daten aus?


Wenn die Liste1 und Liste2 beide die gleichen einzigartigen Elemente beinhalten, reicht es bei gleicher Sortierung alle Elemente um eine Position zu verschieben.

Code: Alles auswählen

Liste1 = ["Apfel", "Banane", "Birne", "Traube", "Kirsche", "Melone"]
Liste2 = ["Apfel", "Banane", "Birne", "Traube", "Kirsche", "Melone"]

List1.insert(0,Liste1.pop())

print(List1)
print(List2)
Kommen Elemente mehrmals vor, funktioniert das im Allgemeinen nicht mehr.

Als Schleife:

Code: Alles auswählen

import random

Liste1 = ["Apfel", "Banane", "Birne", "Traube", "Kirsche", "Melone"]
Liste2 = ["Apfel", "Banane", "Birne", "Traube", "Kirsche", "Melone"]

counter = 0
for i, obst in enumerate(Liste1):
    while obst == Liste2[i]:
        Liste2[i:] = random.shuffle(Liste2[i:])
        counter += 1
        if counter == 10_000:
            break
    if counter == 10_000:
        break

print(Liste1)
print(Liste2)
Je nach Beschaffenheit von Liste1 wird das ohne den counter niemals abbrechen, z.B. wenn über die Hälfte der Einträge nur Äpfel sind.
Auch kann es zu Situationen in langen Listen kommen, in denen fast alle verbleibenden Einträge in Liste2 gleich dem aktuellen 'Obst' sind.
Mit genug Pech kann shuffle hier viel Zeit vergeuden.

Weißt du a priori, dass Liste1 nur einzigartige Elemente beinhaltet und Liste2 eine Kopie ist, kannst du den Counter weglassen:

Code: Alles auswählen

import random

Liste1 = ["Apfel", "Banane", "Birne", "Traube", "Kirsche", "Melone"]
Liste2 = ["Apfel", "Banane", "Birne", "Traube", "Kirsche", "Melone"]

for i, obst in enumerate(Liste1):
    while obst == Liste2[i]:
        Liste2[i:] = random.shuffle(Liste2[i:])

print(Liste1)
print(Liste2)

Können Elemente doppelt vorkommen, müsstest du Fälle wie diesen hier prüfen und vor Beginn der Schleife ausschließen:

Code: Alles auswählen

Liste1 = ["Apfel", "Apfel", "Apfel", "Apfel", "Apfel", "Apfel"]
Liste2 = ["Apfel", "Banane", "Birne", "Traube", "Kirsche", "Melone"]
Hier ist die erste Menge {"Apfel"} und für Apfel aus der zweiten Menge {"Apfel", "Banane", "Birne", "Traube", "Kirsche", "Melone"} findest du in der ersten Menge keinen passenden Partner mehr.

Du suchst eigentlich nach einem "Perfekten Matching" zwischen den beiden Listen. Unter welchen Voraussetzungen kann es das geben?
chrism_iller

__deets__ hat geschrieben: Freitag 10. Juli 2020, 20:09 Mit zip kannst du über beide Listen gleichzeitig laufen. Mit any kannst du prüfen, ob auch nur eines der Paare gleich ist. Und schon hast du dein Prädikat.

Code: Alles auswählen

any(a == b for a, b in zip(l1, l2))
Wobei man wahrscheinlich auch effizienter vorgehen kann, und statt die Liste zu shufflen einfach für jede Stelle zufällig eine neue bestimmt, die nicht die alte sein darf.
Es hat geklappt! Danke schonmal dafür!
Ich versuche nun als nächstes, weitere Bedingungen einzubauen.
Bspw.: Wenn der "Apfel" der "Melone" zugewiesen wurde, kann die "Melone" nicht mehr dem "Apfel" zugewiesen werden.
chrism_iller

Caskuda hat geschrieben: Freitag 10. Juli 2020, 21:58 Wie genau sehen denn die Eingangs-Daten aus?

[...]
Danke für deine umfangreiche Antwort!

- meine Eingangsdaten sind immer einzigartige Elemente
- Liste2 ist immer eine Kopie von Liste1
- das Matching sollte bei jedem Programmstart anders sein, d.h. eine Verschiebung der Elemente aus Liste2 um eine Position ist nicht erwünscht

Ich versuche jetzt als nächstes eine Bedingung einzubauen, die vorschreibt, dass wenn bspw. der "Apfel" der "Melone" zugewiesen wurde, kann die "Melone" nicht mehr dem "Apfel" zugewiesen werden. Liegt so ein Konflikt vor, soll erneut gemischt werden (oder eventuell nach einem Schema vorgegangen werden, welches den Fehler "ausmerzt").
Antworten