@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.
neue Liste
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
+1BlackJack 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.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
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)
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)
Jeder muss mit seinen Mitteln arbeiten und Anfänger haben nunmal die Grundsteine nicht um sämtliche hier gezeigte Lösungen zu verstehen.
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.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 Leben ist wie ein Tennisball.
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.garreth hat geschrieben:Also hier mal meine anfängerfreundliche Lösung:
@garreth: ``lambda`` ist überflüssig wenn es bloss eine Funktion mit den selben Argumenten aufruft die es selbst bekommen hat.
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]
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]
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.sparrow hat geschrieben:Hi Garreth,
deine beiden Lösungen verhalten sich anders als das was der Threadstarter gepostet hat.
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]
Unter der Annahme, dass n ganzzahlig ist:
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.
Code: Alles auswählen
[(min(n, 33) + 3) // 3 for n in numbers if n > 0]
Zuletzt geändert von snafu am Dienstag 10. Februar 2015, 15:15, insgesamt 1-mal geändert.
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:sparrow hat geschrieben:Die Sonderfälle werden auch unter Python3 nicht berücksichtigt:
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)
Zuletzt geändert von garreth am Dienstag 10. Februar 2015, 16:01, insgesamt 1-mal geändert.
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.
- 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...
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.
Code: Alles auswählen
if result = i / 3.0+0.5 and i % 3 != 0:
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
Nein und ja, ich habe ihn schon mal laufen lassen, allerdings noch mal hier abgetippt. Der Fehler hat sich dann eingeschlichen.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.
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)
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.
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.
- 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:
(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!
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 )
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
assert encoding_kapiert
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.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.
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)
Danke an Hyperion für den Tip mit dem erwartet Vergleich, macht die Angelegenheit wesentlich einfacher!
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Danke mir vor allem für den Hinweis auf Unit Testing! Befasse Dich damit ruhig, auch wenn das außerhalb des eigentlichen Problems hier stehtgarreth hat geschrieben: Danke an Hyperion für den Tip mit dem erwartet Vergleich, macht die Angelegenheit wesentlich einfacher!
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
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!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