Lambda und Filter

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
winter-mute
User
Beiträge: 4
Registriert: Dienstag 18. Juli 2017, 14:51

Hallo zusammen,

ich bin neulich an das Thema Lambda und Filter gekommen. Soweit ich verstanden habe, sind Lambda´s anonyme Funktionen/Methoden sind und die Filter den Datenfluss nach bestimmten Bedingungen herausfiltern und das was überbleibt zurückliefern. Nun ist es ja relativ gut verständlich. Problematisch wird bei der Syntax. Ich hatte als Aufgabe eine Liste durchzuarbeiten und die Zahlen aufsteigend sortieren. Dabei musste beachtet werden, dass nur positive Zahlen berücksichtigt werden und alle negativen Zahlen ihre Position nicht verändern dürfen. Beispiel so einer Liste:
[-1, 150, 190, 170, -1, -1, 160, 180]

Nun habe ich das gelöst auf die übliche Anfänger Art und Weise. Im Internet habe ich jedoch eine andere Lösung gefunden, der ich nur bedingt folgen kann:

Code: Alles auswählen

def sortedList(list1):
  list2 = sorted(filter(lambda x: x != -1, list1), reverse=True)
  return [list2.pop() if elem != -1 else elem for elem in list1]
Soweit ich verstanden habe, wird in der ersten Zeile wird die list1 rückwärts iteriert und alles was nicht -1 ist, wird dementsprechen in die list2 reingespeichert, absteigend sortiert.
Bei der zweiten Zeile wird für mich ein bisschen unübersichtlich. Meine Interpretation wäre:
Wenn das elem nicht -1 ist, schreibt das elem an die Stelle des elem in der list1.

Nun muss ich sagen, dass wärend ich diesen Beitrag geschrieben habe, diesen Teil "[...]else elem for elem in list1" zum ersten Mal erklären konnte, bzw. ins Deutsch übersetzen konnte. Ist meine Interpretation richtig? Könnt ihr vielleicht mir noch etwas dazu erzählen?

Besten Dank und Gruß

winter-mute
Zuletzt geändert von Anonymous am Donnerstag 20. Juli 2017, 21:33, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@winter-mute: in der ersten Zeile wird nichts rückwärts iteriert, wo liest Du das raus? Die zweite Zeile ist sehr undurchsichtig. So etwas sollte man nicht schreiben. Es ist nicht auf den ersten Blick klar, warum list2 absteigend sortiert werden muß.

Verständlicher wäre wohl

Code: Alles auswählen

def sortedList(numbers):
    sorted_numbers = iter(sorted(filter(lambda x: x != -1, numbers)))
    return [next(sorted_numbers) if elem != -1 else elem for elem in numbers]
winter-mute
User
Beiträge: 4
Registriert: Dienstag 18. Juli 2017, 14:51

Danke für den Hinweis, wieder was gelernt!
Ich dachte, reverse=True würde die Liste umdrehen. Ich habe mich falsch ausgedrückt. Aber, dass bei filter() durch die Liste iteriert wird ist doch richtig oder?

Wie gesagt, bin ein blutiger Anfänger. Nun muss ich auch sagen, dass mir leider bei deiner Lösung etwas verständnis fehlt...

Kannst du mir vielleicht einige Funktionen etwas erklären?
iter(): Iteriert es durch die Liste und vergleicht jedes Element mit den restlichen Elementen?
next(): Was macht das denn genau? Springt es einfach zum nächsten Element, wenn die Bedingung nicht erfüllt ist?
skirnir
User
Beiträge: 33
Registriert: Sonntag 25. Januar 2015, 10:59

winter-mute hat geschrieben: Ich dachte, reverse=True würde die Liste umdrehen.
Das stimmt schon, aber schau dir die Klammerung an. 'reverse=True' ist ein Parameter der sorted-Funktion. Das heißt, es wird nicht rückwärts iteriert, sondern das Ergebnis der filter-Funktion wird absteigend sortiert.
Aber, dass bei filter() durch die Liste iteriert wird ist doch richtig oder?
Ja.
iter(): Iteriert es durch die Liste und vergleicht jedes Element mit den restlichen Elementen?
Nein. iter liefert ein iterator Objekt (s.u.)
next(): Was macht das denn genau? Springt es einfach zum nächsten Element, wenn die Bedingung nicht erfüllt ist?
Nein, es gibt da keine Bedingung. next gibt das nächste Element des iterators zurück. Die Kombination von iter und next macht es hier unnötig, die Liste absteigend zu sortieren.
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

filter() mit Lambda ist Geschmackssache. Ich nutze da lieber einen Generator, zumal die Performance dann meist besser ist. In diesem Fall sieht das dann so aus:

Code: Alles auswählen

numbers = [-1, 150, 190, 170, -1, -1, 160, 180]
positives = iter(sorted(n for n in numbers if n >= 0))
print([
    (next(positives) if n >= 0 else n) for n in numbers
])
Antworten