Tutorial

Verwenden der Python-Filterfunktion

PythonDevelopment

Einführung

Die in Python integrierte filter()-Funktion kann dazu dienen, aus einem vorhandenen iterable (wie einer Liste oder einem Wörterbuch) einen neuen iterator zu erstellen, der Elemente mithilfe einer von uns bereitgestellten Funktion effizient filtern kann. Ein iterable ist ein Python-Objekt, bei dem „iterated over“ möglich ist, d. h. Elemente werden in einer Reihenfolge zurückgegeben, die wir in einer for-Schleife verwenden können.

Die grundlegende Syntax für die Funktion filter() lautet:

filter(function, iterable)

Dadurch wird ein Filterobjekt zurückgegeben, das ein iterable ist. Wir können eine Funktion wie list() verwenden, um eine Liste aller in einem Filterobjekt zurückgegebenen Elemente zu erstellen.

Die Funktion filter() bietet eine Möglichkeit, Werte zu filtern, die oft effizienter ist als eine Listen-Abstraktion, insbesondere wenn wir mit größeren Datensätzen arbeiten. Beispielsweise erstellt eine Listen-Abstraktion eine neue Liste, was die Laufzeit dieser Verarbeitung erhöht. So verfügen wir, nachdem unsere Listen-Abstraktion ihren Ausdruck abgeschlossen hat, über zwei Listen im Arbeitsspeicher. Allerdings wird filter() ein einfaches Objekt erstellen, das einen Verweis auf die Originalliste, die bereitgestellte Funktion und einen Index enthält, wo in der Originalliste gesucht werden soll. Dafür wird weniger Arbeitsspeicher benötigt.

In diesem Tutorial werden wir uns vier verschiedene Methoden zur Verwendung von filter() ansehen: mit zwei verschiedenen iterable-Strukturen, mit einer lambda-Funktion und ohne definierte Funktion.

Verwenden von filter() mit einer Funktion

Das erste Argument für filter() ist eine Funktion, mit der wir entscheiden, ob die einzelnen Elemente enthalten sein oder herausgefiltert werden sollen. Die Funktion wird für jedes Element im iterable, das als zweites Argument übergeben wird, einmal aufgerufen, und bei jeder Rückgabe von False wird der Wert gelöscht. Da dieses Argument eine Funktion ist, können wir entweder eine normale Funktion übergeben oder lambda-Funktionen nutzen, insbesondere wenn der Ausdruck weniger komplex ist.

Im Folgenden wird die Syntax einer lambda-Funktion mit filter() dargestellt:

filter(lambda item: item[] expression, iterable)

Mit einer Liste wie dieser können wir eine lambda-Funktion mit einem Ausdruck integrieren, gegen den wir die einzelnen Elemente aus der Liste bewerten möchten:

creature_names = ['Sammy', 'Ashley', 'Jo', 'Olly', 'Jackie', 'Charlie']

Um die Liste zu filtern und die Namen unserer Aquariumbewohner zu finden, die mit einem Vokal beginnen, können wir die folgende lambda-Funktion ausführen:

print(list(filter(lambda x: x[0].lower() in 'aeiou', creature_names)))

Hier deklarieren wir einen Punkt in unserer Liste als x. Dann legen wir unseren Ausdruck so fest, dass er auf das erste Zeichen der jeweiligen Zeichenfolge (oder Zeichen „zero“) zugreift, also x[0]. Durch Kleinschreibung aller Namen wird sichergestellt, dass Buchstaben mit der Zeichenfolge in unserem Ausdruck (aeiou) abgeglichen werden.

Abschließend übergeben wir das iterable creature_names. Wie im vorherigen Abschnitt wenden wir list() auf das Ergebnis an, um eine Liste aus den iterator filter()-Ergebnissen zu erstellen.

Die Ausgabe wird wie folgt aussehen:

Output
['Ashley', 'Olly']

Das gleiche Ergebnis kann mit einer selbst definierten Funktion erzielt werden:

creature_names = ['Sammy', 'Ashley', 'Jo', 'Olly', 'Jackie', 'Charlie']

def names_vowels(x):
  return x[0].lower() in 'aeiou'

filtered_names = filter(names_vowels, creature_names)

print(list(filtered_names))

Unsere Funktion names_vowels definiert den Ausdruck, den wir implementieren werden, um creature_names zu filtern.

Die Ausgabe würde erneut wie folgt aussehen:

Output
['Ashley', 'Olly']

Im Allgemeinen erzielen lambda-Funktionen mit filter() das gleiche Ergebnis, wie wenn wir eine reguläre Funktion verwenden würden. Die Notwendigkeit zur Definition einer regulären Funktion wächst mit der Komplexität der Ausdrücke zum Filtern unserer Daten. Dadurch lässt sich in unserem Code wahrscheinlich auch eine bessere Lesbarkeit erzielen.

Verwenden von None mit filter()

Wir können None als erstes Argument an filter() übergeben, damit der zurückgegebene iterator alle Werte ausgibt, die Python als „falsy“ erachtet. Im Allgemeinen betrachtet Python alles mit einer Länge von 0 (wie eine leere Liste oder eine leere Zeichenfolge) und alles, was 0 numerisch entspricht, als „false“, daher die Verwendung des Begriffs „falsy“.

Im folgenden Fall möchten wir unsere Liste so filtern, dass nur die Tanknummern unseres Aquariums angezeigt werden:

aquarium_tanks = [11, False, 18, 21, "", 12, 34, 0, [], {}]

In diesem Code haben wir eine Liste, die Integer, leere Sequenzen und einen booleschen Wert enthält.

filtered_tanks = filter(None, aquarium_tanks)

Wir verwenden die Funktion filter() mit None und übergeben die Liste aquarium_tanks als unser iterable. Da wir None als erstes Argument übergeben haben, prüfen wir, ob die Elemente in unserer Liste als false angesehen werden.

print(list(filtered_tanks))

Dann schließen wir filtered_tanks in eine list()-Funktion ein, damit sie beim Drucken eine Liste für filtered_tanks zurückgibt.

Hier sehen wir, dass die Ausgabe nur die Integerwerte enthält. Alle Elemente, die zu False ausgewertet wurden oder der Länge 0 entsprechen, wurden durch filter() entfernt:

Output
[11, 25, 18, 21, 12, 34]

Anmerkung: Wenn wir list() nicht verwenden und filtered_tanks drucken, erhalten wir ein Filterobjekt, das etwa so aussieht: <Filter object at 0x7fafd5903240>. Das Filterobjekt ist ein iterable, sodass wir ein loop over mit for vornehmen können; alternativ können wir list() verwenden, um es in eine Liste umzuwandeln. Dies tun wir hier, da es eine gute Möglichkeit ist, die Ergebnisse zu prüfen.

Bei None haben wir filter() verwendet, um Elemente aus unserer Liste schnell zu entfernen, die als false betrachtet wurden.

Verwenden von filter() mit einer Liste von Wörterbüchern

Wenn wir eine komplexere Datenstruktur aufweisen, können wir filter() dennoch verwenden, um die einzelnen Elemente zu bewerten. Wenn wir beispielsweise über eine Liste von Wörterbüchern verfügen, wollen wir nicht nur über jedes einzelne Element in der Liste – einem der Wörterbücher – iterieren, sondern wollen ggf. auch über jedes key:value-Paar in einem Wörterbuch iterieren, um alle Daten auszuwerten.

Als Beispiel gehen wir davon aus, dass wir eine Liste jedes einzelnen Tiers in unserem Aquarium sowie verschiedene Details zu ihnen haben:

aquarium_creatures = [
  {"name": "sammy", "species": "shark", "tank number": "11", "type": "fish"},
  {"name": "ashley", "species": "crab", "tank number": "25", "type": "shellfish"},
  {"name": "jo", "species": "guppy", "tank number": "18", "type": "fish"},
  {"name": "jackie", "species": "lobster", "tank number": "21", "type": "shellfish"},
  {"name": "charlie", "species": "clownfish", "tank number": "12", "type": "fish"},
  {"name": "olly", "species": "green turtle", "tank number": "34", "type": "turtle"}
]

Wir möchten diese Daten mit einer Suchzeichenfolge filtern, die wir der Funktion übergeben. Damit filter() auf jedes Wörterbuch und jedes Element in den Wörterbüchern zugreift, richten wir eine geschachtelte Funktion ein, die wie folgt aussieht:

def filter_set(aquarium_creatures, search_string):
    def iterator_func(x):
        for v in x.values():
            if search_string in v:
                return True
        return False
    return filter(iterator_func, aquarium_creatures)

Wir definieren eine filter_set()-Funktion, die aquarium_creatures und search_string als Parameter verwendet. In filter_set() übergeben wir unsere iterator_func() als Funktion an filter(). Die Funktion filter_set() gibt den iterator zurück, der aus filter() resultiert.

Die iterator_func() nimmt x als Argument, was ein Element in unserer Liste (d. h. einem einzelnen Wörterbuch) darstellt.

Als Nächstes greift die for-Schleife auf die Werte in den einzelnen key:value-Paaren in unseren Wörterbüchern zu und nutzt dann eine bedingte Anweisung, um zu prüfen, ob die search_string in v ist, was einen Wert darstellt.

Wie in unseren vorherigen Beispielen: Wenn der Ausdruck zu True auswertet, fügt die Funktion das Element dem Filterobjekt hinzu. Dieses wird zurückgegeben, sobald die Funktion filter_set() abgeschlossen ist. Wir positionieren return False außerhalb unserer Schleife, damit jedes Element in jedem Wörterbuch geprüft wird, anstatt nach der Überprüfung des ersten Wörterbuchs zurückzukehren.

Wir rufen filter_set() mit unserer Liste der Wörterbücher und der Suchzeichenfolge auf, für die wir Übereinstimmungen finden möchten:

filtered_records = filter_set(aquarium_creatures, "2")    

Nach Abschluss der Funktion ist unser Filterobjekt in der Variable filtered_records gespeichert, die wir in eine Liste verwandeln und drucken:

print(list(filtered_records))      

Wir sehen die folgende Ausgabe aus diesem Programm:

Output
[{'name': 'ashley', 'species': 'crab', 'tank number': '25', 'type': 'shellfish'}, {'name': 'jackie', 'species': 'lobster', 'tank number': '21', 'type': 'shellfish'}, {'name': 'charlie', 'species': 'clownfish', 'tank number': '12', 'type': 'fish'}]

Wir haben die Liste der Wörterbücher mit der Suchzeichenfolge 2 gefiltert. Wir können sehen, dass die drei Wörterbücher zurückgegeben wurden, die eine Tanknummer mit 2 enthielten. Mit unserer eigenen geschachtelten Funktion können wir auf jedes einzelne Element zugreifen und effizient mit der Suchzeichenfolge abgleichen.

Zusammenfassung

In diesem Tutorial haben wir die verschiedenen Möglichkeiten zur Verwendung der Funktion filter() in Python kennengelernt. Jetzt können Sie filter() mit Ihrer eigenen Funktion, einer lambda-Funktion oder mit None verwenden, um in Datenstrukturen unterschiedlicher Komplexität nach Elementen zu filtern.

Zwar haben wir in diesem Tutorial die Ergebnisse von filter() sofort im Listenformat gedruckt, doch ist es wahrscheinlich, dass wir das zurückgegebene filter()-Objekt in unseren Programmen verwenden und die Daten weiter bearbeiten werden.

Wenn Sie mehr über Python erfahren möchten, lesen Sie unsere Reihe Codieren in Python 3 und unsere Python Themenseite.

Creative Commons License