Seite 1 von 1

Liste nach mehreren Strings durchsuchen?

Verfasst: Donnerstag 26. März 2009, 16:14
von shadow07
ich hänge mal wieder:
ich suche in einer Liste nach Suchstring und Endung - funktioniert soweit. Nun möchte ich aber mehrere Endungen als Wahr akzeptieren, wie kann ich das anstellen?

Liste1 = [freund.mpeg, feind.mpg, butter.mpeg, brot.wav, wurst.wrs]
Liste2 = [mpg, mpeg]

Code: Alles auswählen

Endung = "mpg"
Suchstring = "*nd*"
if name.endswith(Endung) is True and fnmatch.fnmatch(name.lower(),Suchstring) is True:
    Dateiliste.append(( name, fullpath ))
Ergebnis:
feind,

Code: Alles auswählen

# funktioniert so natürlich nicht mehr
Endung = "mpg, mpeg"
Suchstring = "*nd*"
if name.endswith(Endung) is True and fnmatch.fnmatch(name.lower(),Suchstring) is True:
    Dateiliste.append(( name, fullpath ))
Wunschergebnis:
freund, feind

Verfasst: Donnerstag 26. März 2009, 16:19
von Leonidas

Code: Alles auswählen

[word for word in liste1 if any(map(lambda x: x in word, liste2))]
Leider geht ``operator.contains`` nicht mit Keyword-Argumenten (wie str1442 schon festgestellt hat), sonst ginge es hübscher.

Verfasst: Donnerstag 26. März 2009, 16:32
von BlackJack
@shadow07: ``is`` prüft auf Objektidentität, nicht auf Wertegleichheit. Das sollte man wirklich nur in Fällen verwenden, wo man exakt auf ein bestimmtes Objekt prüfen möchte, und das möchte man eigentlich relativ selten. Im Regelfall nur, wenn das Objekt, auf das man prüfen möchte, ein Singleton ist, wie zum Beispiel `None`. Das Konzept von "Wahr" und "Falsch" beschränkt sich in Python aber nicht auf die beiden Objekte, die an die Namen `True` und `False` gebunden sind.

Aber selbst ein ``==`` wäre hier überflüssig, weil die beiden Funktionsaufrufe selbst ja schon Wahrheitswerte zurückgeben, die braucht man also nicht noch einmal mit einem Wahrheitswert zu vergleichen um dann doch nur wieder einen Wahrheitswert zu bekommen.

Ansonsten wirst Du halt die Endungen einzeln prüfen müssen. Eventuell in einer Schleife und die in eine Funktion ausgelagert, damit es nicht zu unübersichlich wird.

Du könntest auch eine Funktion schreiben, die alle Prüfungen für einen Namen enthält, und dann zum Beispiel die neue Dateiliste mit `filter()` aus der alten erstellen.

@Leonidas: `operator.contains()` sollte trotzdem mit `functools.partial()` verwendbar sein, falls es das wäre was Du hübscher fändest, aber ich glaube einfacher wäre dass hier: ``any(x in word for x in liste2)``

Verfasst: Donnerstag 26. März 2009, 16:39
von Leonidas
@BlackJack: Ja, so meinte ich es. Tatsächlich, das würde gehen; ich hatte beim Testen die Reihenfolge der Parameter andersrum und das ging nicht. Natürlich habe ich wiedereinmal viel zu kompliziert gedacht :evil:

Verfasst: Donnerstag 26. März 2009, 16:58
von shadow07
ich habe das jetzt so verwendet:

Code: Alles auswählen

Findliste2 = [element for element in Dateiliste if any(map(lambda x: x in element, self.eEndung2))]
was aber offenbar nicht geht, denn ich bekomme weit mehr Ergebnisse, welche nicht mit Elementen von self.eEndung2 übereinstimmen

@BlackJack
ich habe das ``is` entfernt, danke für den Hinweis

die Endungen einzeln überprüfen bekomme ich nicht hin, weil erstens die Anzahl der Endungen unterschiedlich sein kann (bei einer Suche 3, bei einer anderen Suche 6) und ich zweitens endlose or-Ketten vermeiden möchte

ich habe praktisch eine vorgefilterte Liste mit Dateinamen, welche dem Suchstring entsprechen. Die Liste will ich nun nochmal filtern nach einer oder mehreren per Variablen-Liste übergebenen Endungen
(oder alles in einem Rutsch wäre genialer)

Verfasst: Donnerstag 26. März 2009, 17:04
von derdon
Blackjack hat geschrieben:[...] einfacher wäre dass hier: ``any(x in word for x in liste2)``
@shadow07: Und warum benutzt du dann die kompliziertere Variante?

Verfasst: Donnerstag 26. März 2009, 17:25
von shadow07
Und warum benutzt du dann die kompliziertere Variante?
vermutlich, weil ich zu dämlich bin den Codefetzen sinnvoll zu benutzen :(
(und eine Suche mir ein paar hundert Seiten beschert wo alle bisher gelesenen any als Kommentar oä enthielten)

Verfasst: Donnerstag 26. März 2009, 17:30
von Leonidas

Code: Alles auswählen

[word for word in liste1 if any(x in word for x in liste2)]

Verfasst: Donnerstag 26. März 2009, 17:32
von derdon

Verfasst: Donnerstag 26. März 2009, 18:04
von shadow07
also beide Varianten gehen nicht (Ergebnis nichts):

Code: Alles auswählen

for word in Dateiliste:
				if any(x in word for x in self.eEndung2):
					Dateiliste2.append(word)

Code: Alles auswählen

Dateiliste2 = [word for word in Dateiliste if any(x in word for x in self.eEndung2)]

Verfasst: Donnerstag 26. März 2009, 18:12
von Leonidas
Mach mal ein

Code: Alles auswählen

print repr(Dateiliste)
print repr(self.eEndung2)
in deinem Code und poste das Ergebnis.

Verfasst: Donnerstag 26. März 2009, 18:53
von shadow07
Mach mal ein
ist nicht so einfach, da einiges importiert wird was nur auf der GUI läuft, müsste alles zerlegen - aber so läufts:

Code: Alles auswählen

if fnmatch.fnmatch(name.lower(),Suchstring):
    if any(x in name for x in self.eEndung):
        Dateiliste.append(( name, fullpath ))
also hat mich dein Print-Hinweis doch auf die Lösung gebracht, denn die Liste ist offenbar ungeeignet, wenn ich aber sofort am Anfang prüfen lasse dann gehts ja

vielen Dank euch :D