neue Liste

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.
BlackJack

@haeuslermartin: So verschieden sind die Vorschläge nicht, die laufen in *Python* letztendlich alle auf sehr ähnliche „list comprehension”-Ausdrücke hinaus. Falls das nicht klar geworden sein sollte: Da sind Lösungen dabei die nicht in Python sondern in verschiedenen Lisp-Dialekten geschrieben sind. Die sehen natürlich etwas anders aus als Python, aber die Idee dahinter ist immer sehr ähnlich.

Die `tranform_number()`-Funktion die Sirius3 erwähnt hat ist natürlich nichts was in Deinem Buch vorkommt, die gibt es nämlich (noch) gar nicht, sondern die müsstest *Du* schreiben.

Wie schon gesagt wurde ist die „anfängerfreundliche Lösung” keine sinnvolle Lösung. Das würde niemand der bei Verstand ist so schreiben. Ausser Anfänger vielleicht, aber für die ist diese Lösung auch nur geeignet um zu zeigen wie man es *nicht* machen würde, und ein Anfänger sollte dringend versuchen eine vernünftige Lösung zu finden oder zu verstehen.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

BlackJack hat geschrieben: Wie schon gesagt wurde ist die „anfängerfreundliche Lösung” keine sinnvolle Lösung. Das würde niemand der bei Verstand ist so schreiben. Ausser Anfänger vielleicht, aber für die ist diese Lösung auch nur geeignet um zu zeigen wie man es *nicht* machen würde, und ein Anfänger sollte dringend versuchen eine vernünftige Lösung zu finden oder zu verstehen.
+1 :!:
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
garreth
User
Beiträge: 41
Registriert: Donnerstag 23. Oktober 2014, 12:04

Code: Alles auswählen

from math import ceil
alle = [20, 33, 21, 32, 27, 7, 25, 16, 32, 27, 21, 22]
alle = list(map(lambda x: ceil(x/3), alle))
print(alle)
ohne import:

Code: Alles auswählen

def transform_number(i):
    result = i / 3
    if result < i//3+0.5 and i % 3 != 0:
        result += 1
    return round(result)

if __name__ == '__main__':
    alle = [20, 33, 21, 32, 27, 7, 25, 16, 32, 27, 21, 22]
    alle = list(map(lambda x: transform_number(x), alle))
    print(alle)
So und jetzt nochmals, ich habe nie behauptet, dass die "anfängerfreundliche Lösung" eine Lösung für den produktiven Einsatz ist. Es ist ein Beispiel, an dem man die Funktion einer if-elif-else Abfrage gut nachvollziehen können sollte. Nicht mehr, nicht weniger.
Jeder muss mit seinen Mitteln arbeiten und Anfänger haben nunmal die Grundsteine nicht um sämtliche hier gezeigte Lösungen zu verstehen.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

garreth hat geschrieben:So und jetzt nochmals, ich habe nie behauptet, dass die "anfängerfreundliche Lösung" eine Lösung für den produktiven Einsatz ist. Es ist ein Beispiel, an dem man die Funktion einer if-elif-else Abfrage gut nachvollziehen können sollte. Nicht mehr, nicht weniger.
Das ist es ja gerade nicht. Der Code zeigt nämlich nur gut, wann genau man ein ein if/elif/else *nicht* einsetzen sollte. Der TE hat ja wohl eher weniger Probleme mit bedingten Anweisungen an sich, sondern wann man diese einsetzt und wann Code sinnvoll in (in Schleifen) zusammengefasst werden kann. Und wenn du das Konstrukt erklären möchtest, dann braucht es dazu keine 10 elif-Zweige. Zwei Stück in einem sinnvollen Szenario hätten gereicht.
Das Leben ist wie ein Tennisball.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

garreth hat geschrieben:Also hier mal meine anfängerfreundliche Lösung:
Das zeigt sehr schön, wie genau Programmierung *nicht* funktioniert. Auch nicht für einen Anfänger. Aber das wurde ja bereits mehrfach auch von anderen kritisiert.
BlackJack

@garreth: ``lambda`` ist überflüssig wenn es bloss eine Funktion mit den selben Argumenten aufruft die es selbst bekommen hat.
Benutzeravatar
sparrow
User
Beiträge: 4195
Registriert: Freitag 17. April 2009, 10:28

Hi Garreth,

deine beiden Lösungen verhalten sich anders als das was der Threadstarter gepostet hat.

[codebox=python file=x]alle = [20,33,21,32,27,7,25,16,32,27,21,22,44,55,12, -1, 2]

def original(alle):
result = []
for i in (alle):
if i >0 and i<4:
result.append(1)
if i >3 and i<7:
result.append(2)
if i >6 and i<10:
result.append(3)
if i >9 and i<13:
result.append(4)
if i >12 and i<16:
result.append(5)
if i >15 and i<19:
result.append(6)
if i >18 and i<22:
result.append(7)
if i >21 and i<25:
result.append(8)
if i >24 and i<28:
result.append(9)
if i >27 and i<31:
result.append(10)
if i >30 and i<34:
result.append(11)
elif i>33:
result.append(12)
return result


def gareth1(alle):
from math import ceil
alle = list(map(lambda x: ceil(x/3), alle))
return alle


def gareth2(alle):
def transform_number(i):
result = i / 3
if result < i//3+0.5 and i % 3 != 0:
result += 1
return round(result)
return list(map(lambda x: transform_number(x), alle))[/code]

Code: Alles auswählen

>>> alle
[20, 33, 21, 32, 27, 7, 25, 16, 32, 27, 21, 22, 44, 55, 12, -1, 2]
>>> original(alle)
[7, 11, 7, 11, 9, 3, 9, 6, 11, 9, 7, 8, 12, 12, 4, 1]
>>> gareth1(alle)
[6.0, 11.0, 7.0, 10.0, 9.0, 2.0, 8.0, 5.0, 10.0, 9.0, 7.0, 7.0, 14.0, 18.0, 4.0, -1.0, 0.0]
>>> gareth2(alle)
[7.0, 11.0, 7.0, 11.0, 9.0, 3.0, 9.0, 6.0, 11.0, 9.0, 7.0, 8.0, 15.0, 19.0, 4.0, 0.0, 1.0]
garreth
User
Beiträge: 41
Registriert: Donnerstag 23. Oktober 2014, 12:04

sparrow hat geschrieben:Hi Garreth,

deine beiden Lösungen verhalten sich anders als das was der Threadstarter gepostet hat.
Manchmal vergesse ich zu erwähnen, dass ich ausschließlich Python 3 programmiere. Der Fehler tritt nur in Python 2 auf und muss natürlich in diesem Fall angepasst werden.
Benutzeravatar
sparrow
User
Beiträge: 4195
Registriert: Freitag 17. April 2009, 10:28

Die Sonderfälle werden auch unter Python3 nicht berücksichtigt:

Code: Alles auswählen

# python3 -i test.py
>>> alle
[20, 33, 21, 32, 27, 7, 25, 16, 32, 27, 21, 22, 44, 55, 12, -1, 2]
>>> original(alle)
[7, 11, 7, 11, 9, 3, 9, 6, 11, 9, 7, 8, 12, 12, 4, 1]
>>> gareth1(alle)
[7, 11, 7, 11, 9, 3, 9, 6, 11, 9, 7, 8, 15, 19, 4, 0, 1]
>>> gareth2(alle)
[7, 11, 7, 11, 9, 3, 9, 6, 11, 9, 7, 8, 15, 19, 4, 0, 1]
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Unter der Annahme, dass n ganzzahlig ist:

Code: Alles auswählen

[(min(n, 33) + 3) // 3 for n in numbers if n > 0]
EDIT: Den funktional orientierten Lösungen entnehme ich meinen Denkfehler, dass nur 2 addiert werden darf. Sonst liefern alle Vielfachen von 3 das falsche Ergebnis.
Zuletzt geändert von snafu am Dienstag 10. Februar 2015, 15:15, insgesamt 1-mal geändert.
garreth
User
Beiträge: 41
Registriert: Donnerstag 23. Oktober 2014, 12:04

sparrow hat geschrieben:Die Sonderfälle werden auch unter Python3 nicht berücksichtigt:
So nun speziell für sparrow unter Berücksichtigung der Sonderfälle, lauffähig unter Python 2 und mit anschaulicher Darstellung einer if-elif-else Abfrage:

Code: Alles auswählen

def transform_number(i):
    if i < 1:
        return False
    elif i > 33:
        return 12
    else:
        result = i / 3.0
        if result == i / 3.0+0.5 and i % 3 != 0:
            result += 1
        return int(round(result))

if __name__ == '__main__':
    alle = [20, 33, 21, 32, 27, 7, 25, 16, 32, 27, 21, 22, 44, 55, 12, -1, 2]
    print(alle)
    alle = list(filter(None,map(transform_number,alle)))
    print(alle)
Danke an blackjack für den Hinweis.
Zuletzt geändert von garreth am Dienstag 10. Februar 2015, 16:01, insgesamt 1-mal geändert.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

haeuslermartin hat geschrieben:Die Zahll der ursprünglichen Listeneinträge bleibt bei 12, im Endeffekt soll immer nur ein neuer Eintrag hinzukommen, dafür fällt der letzte aber raus.

Code: Alles auswählen

from collections import deque

numbers = ((min(n, 33) + 2) // 3 for n in all_numbers if n > 0)
result = deque(numbers, 12)
print(list(result))
Zuletzt geändert von snafu am Dienstag 10. Februar 2015, 15:27, insgesamt 1-mal geändert.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

@garreth: Den Code hast Du doch nie laufen lassen‽ Da ist ein Syntaxfehler in Zeile 8...

Code: Alles auswählen

if result = i / 3.0+0.5 and i % 3 != 0:
Abgesehen davon empfinde ich diese Berechnung als unelegant. Und wie man das anschaulicher und vermutlich auch effizienter berechnet ist ja nun schon gezeigt worden. Und eine Mischung aus Integer- und booleschen Rückgabewerten empfinde ich auch als wenig gelungen. Da sollte man die Filterung vor verlagern, wie es bei den Lösungen mit List Comprehensions auch gemacht worden ist.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
garreth
User
Beiträge: 41
Registriert: Donnerstag 23. Oktober 2014, 12:04

Hyperion hat geschrieben:@garreth: Den Code hast Du doch nie laufen lassen‽ Da ist ein Syntaxfehler in Zeile 8...
Abgesehen davon empfinde ich diese Berechnung als unelegant. Und wie man das anschaulicher und vermutlich auch effizienter berechnet ist ja nun schon gezeigt worden. Und eine Mischung aus Integer- und booleschen Rückgabewerten empfinde ich auch als wenig gelungen. Da sollte man die Filterung vor verlagern, wie es bei den Lösungen mit List Comprehensions auch gemacht worden ist.
Nein und ja, ich habe ihn schon mal laufen lassen, allerdings noch mal hier abgetippt. Der Fehler hat sich dann eingeschlichen.
Du hast Recht, die Berechnung ist unelegant deswegen nochmal ein neuer Versuch:

Code: Alles auswählen

def transform_number(i):
    if i < 1:
        return 0
    elif i > 33:
        return 12
    else:
        if i % 3 == 0:
            return int(i/3)
        else:   
            return int(i/3+1)

if __name__ == '__main__':
    alle = [20, 33, 21, 32, 27, 7, 25, 16, 32, 27, 21, 22, 44, 55, 12, -1, 2]
    print(alle)
    alle = list(filter(None,map(transform_number, alle)))
    print(alle)
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Dein neuer Code ist leider wieder falsch. Im Original soll bei einer 3 eine 1 ausgeliefert werden. Bei dir würde bei einer 3 (oder einer 6 oder einer 9 ...) eine 0 (bzw 1 bzw 2 ...) rauskommen. Erkennst du den Fehler? ;)

Du musst im Grunde gar nicht unterscheiden, ob bei einer Division durch 3 ein Rest rauskommt, sondern du musst die Zahl nur so "vorbereiten", dass die ganzzahlige Division das gewünschte Ergebnis liefert. Das kann man ja im Kopf mal anhand einiger Beispiele durchrechnen.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Und vor allem könntest Du Dir einen simplen Test schreiben, der das Vergleichen gegenüber der Erwartunsgmenge übernimmt:

Code: Alles auswählen

if __name__ == '__main__':
    erwartet = [7, 11, 7, 11, 9, 3, 9, 6, 11, 9, 7, 8, 12, 12, 4, 1]
    alle = [20, 33, 21, 32, 27, 7, 25, 16, 32, 27, 21, 22, 44, 55, 12, -1, 2]
    print(alle)
    ergebnis = list(filter(None,map(transform_number, alle)))
    print(ergebnis)
    assert(erwartet == ergebnis )
(ich weiß jetzt nicht, ob ich das richtige ``result`` kopiert habe!)

Eigentlich würde man sich dafür einen richtigen Unit Test schreiben, aber für den Anfang und dieses kleine Snippet geht's auch so - auf jeden Fall ist das besser, als gar nicht zu testen! :-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
garreth
User
Beiträge: 41
Registriert: Donnerstag 23. Oktober 2014, 12:04

snafu hat geschrieben:Dein neuer Code ist leider wieder falsch. Im Original soll bei einer 3 eine 1 ausgeliefert werden. Bei dir würde bei einer 3 (oder einer 6 oder einer 9 ...) eine 0 (bzw 1 bzw 2 ...) rauskommen. Erkennst du den Fehler? ;)

Du musst im Grunde gar nicht unterscheiden, ob bei einer Division durch 3 ein Rest rauskommt, sondern du musst die Zahl nur so "vorbereiten", dass die ganzzahlige Division das gewünschte Ergebnis liefert. Das kann man ja im Kopf mal anhand einiger Beispiele durchrechnen.
Diesen Fehler kann ich grad nicht reproduzieren. Ich hab das mal mit den beanstandeten Zahlen versucht Ausgabe ist sowohl in Python 2 als auch Python3 wie vorgesehen.

Aber ich hab mir das mal kurz durch den Kopf gehen lassen. Theoretisch könnte man dies auch so lösen:

Code: Alles auswählen

def transform_number(i):
    if i < 1:
        return 0
    elif i > 33:
        return 12
    else:
        return int((i-0.1)/3+1)

if __name__ == '__main__':
    alle = [20, 33, 21, 32, 27, 7, 25, 16, 32, 27, 21, 22, 44, 55, 12, -1, 2]
    erwartet = [7, 11, 7, 11, 9, 3, 9, 6, 11, 9, 7, 8, 12, 12, 4, 1]
    print(alle)
    alle = list(filter(None,map(transform_number, alle)))
    print(alle)
    print(alle == erwartet)
Würde allerdings nur mit Ganzzahlen funktionieren und die -0.1 ist magisch und meiner Meinung nach schlecht verständlich.

Danke an Hyperion für den Tip mit dem erwartet Vergleich, macht die Angelegenheit wesentlich einfacher!
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

garreth hat geschrieben: Danke an Hyperion für den Tip mit dem erwartet Vergleich, macht die Angelegenheit wesentlich einfacher!
Danke mir vor allem für den Hinweis auf Unit Testing! Befasse Dich damit ruhig, auch wenn das außerhalb des eigentlichen Problems hier steht :-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
garreth
User
Beiträge: 41
Registriert: Donnerstag 23. Oktober 2014, 12:04

Hyperion hat geschrieben:Danke mir vor allem für den Hinweis auf Unit Testing! Befasse Dich damit ruhig, auch wenn das außerhalb des eigentlichen Problems hier steht :-)
Auf jeden Fall, danke dir. Hatte das gestern rausgemacht, weil ich keine Ausgabe hatte. Heute konnte ich mich dann kurz einlesen und ja, wertvoller Tip!
Antworten