Seite 1 von 1

Liste auf gleiche Elemente prüfen

Verfasst: Samstag 15. Mai 2004, 14:37
von Mars
Hallo, ich brauche eine Funktion, die prüft, ob in zwei Listen die gleichen Elemente sind -- unabhängig von der Reihenfolge. Dabei kommt Sortieren nicht in Frage, weil das nur eine Modellfunktion ist und letztlich die Elementen Instanzen einer Klasse sein werden und der Test auf Gleichheit auch durch einen anderen Funktionsaufruf ersetzt wird. Ich habe keine Lust ein spezielles Sortierkriterium zu definieren.

Code: Alles auswählen

def gleich(l1,l2):
    if len(l1) != len(l2):
        return False
    l2c = l2[:]
    for x in l1:
        for y in l2c:
            if x == y:
                l2c.remove(y)
                break
    return not l2c
Weiß jemand einen eleganteren Weg als meinen?

Verfasst: Samstag 15. Mai 2004, 15:03
von fs111
http://python.sandtner.net/viewtopic.php?t=1564 sollte Dir helfen.

Grüße fs111

Verfasst: Samstag 15. Mai 2004, 15:05
von Dookie
Hi Mars,

Code: Alles auswählen

def gleich(l1,l2):
    if len(l1) != len(l2):
        return False
    for item in l1:
        if l1.count(item) != l2.count(item): # if item not in l2: #wenn die Anzahl gleicher egal ist
            break
    else: #for
        return True
    return False
Die geänderte Vergleichsfunktion würde ich dann als Metode __eq__ der Klasse der Instanzen implementieren. Damit müsste die count-Methode der Listen auch funktionieren.


Gruß

Dookie

Verfasst: Samstag 15. Mai 2004, 15:35
von Mars
fs111, das funktioniert wahrscheinlich nicht, wenn man davon ausgeht, dass mehrere gleiche Elemente aber in unterschiedlicher Zahl vorhanden sind:

Code: Alles auswählen

>>> l1 = [1,1,1,2,2,2]
>>> l2 = [2,2,1,1,1,1]
>>> [i for i in l2 if not i in l1]
[]
>>> [i for i in l1 if not i in l2]
[]
--> beide Differenzlisten sind leer; die Listen aber nicht "gleich" für meinen Zweck.

Dookie, die count-Methode verkürzt das ganze schon ein Stück, wenn ich Gleichheit für meine Klasse definiert hätte. Meine Klasse ist aber im wesentlichen ein Paar von floats, für das Gleichheit gefährlich ist. Meine Funktion benutze ich eigentlich nur im Rahmen eines Unittests, wo ich auf ungefähre Gleichheit prüfe, womit ich aber meine Klasse nicht ausstatten will.

Ich glaube, für diesen Fall lasse ich die Funktion, wie sie ist. Wenn ich das gleiche mal mit Integern oder so mache, greife ich auf die count-Methode zurück.

Vielen Dank für die Hilfe! Dieses Forum gefällt mir. :)

Verfasst: Samstag 15. Mai 2004, 15:51
von Dookie
Hi Mars,

schön daß Dir das Forum gefällt :)
Hier mal eine Klasse für floats, wo die Genauigkeit bei Vergleichen in der Klasse definiert ist:

Code: Alles auswählen

class ufloat(float):
    unit = 1.0e-5
    def __cmp__(self, other):
        if abs(self-other) < self.unit:
            return 0
        else:
            return super(ufloat, self).__cmp__(other)
Gruß

Dookie

Verfasst: Samstag 15. Mai 2004, 18:10
von Mars
Das Blöde ist nur, dass so eine festgelegte Genauigkeit eben nur für bestimmte Größenordnungen gültig ist. Fließkommazahlen bestehen eben aus Mantisse und Exponent. Für sehr große Zahlen hilft "unit = 1.0e-5" eben nicht. Man müsste eigentlich eine gewisse Anzahl signifikanter Bits vergleichen.

Im Moment benutze ich assertAlmostEqual aus unittest, das aber das gleiche Problem hat, wie ich nach kurzem Quelltextstudium feststellen konnte. Nun ja, für meine bescheidenen Zwecke reicht es wohl, meistens habe ich eh Zahlen zwischen -1 und 1. :)