Einträge in String löschen

Django, Flask, Bottle, WSGI, CGI…
Antworten
Pitwheazle
User
Beiträge: 871
Registriert: Sonntag 19. September 2021, 09:40

Jetzt sitze ich an Wertetabellen. Die Einträge in die drei Zeilen speichere ich in einer Liste und diese wiederum als String im Protokoll. Ich möchte das "Dezimal" daraus entfernen und stellte mir das ganz einfach vor, aber:

Code: Alles auswählen

                        print(eingabe)
                        eingabe.replace("Decimal", "")
                        print(eingabe)
ergibt:

Code: Alles auswählen

[Decimal('3.6'), Decimal('4.8'), Decimal('6')]
[Decimal('3.6'), Decimal('4.8'), Decimal('6')]
warum geht das denn wieder nicht?
Ich habe es auch mit:

Code: Alles auswählen

                        for e in eingabe:
                            e.replace("Decimal", "")
das geht auch nicht (die Schleife zerlegt den String "eingabe")
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

Der erste Fehler ist, dass Du mit der String-Repräsentation einer Liste etwas anderes machen willst, als ausgeben.
Was ist eigentlich das, was Du erreichen möchtest? Was ist die ursprüngliche Eingabe und wie soll die Ausgabe aussehen?
Pitwheazle
User
Beiträge: 871
Registriert: Sonntag 19. September 2021, 09:40

Ich speichere alle Informationen zu meinen Aufgaben und auch die Auswertung im Protokoll. Da jetzt in der Wertetabelle nicht nur eine Eingabe sondern deren drei sind, speicher ich diese in einer Liste und die Auswertung funktioniert auch wunderbar. Das Protokoll kann man auch anzeigen lassen und das sieht jetzt blöd aus:Bild
Benutzeravatar
__blackjack__
User
Beiträge: 13068
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Pitwheazle: Da wandelt man nicht die Liste in eine Zeichenkette um und versucht *daran* dann nachträglich herum zu basteln, sondern erstellt gleich eine Zeichenkette mit dem Inhalt den man haben will.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Pitwheazle
User
Beiträge: 871
Registriert: Sonntag 19. September 2021, 09:40

Die beiden Listen mit den Eingaben und den Lösungen kann ich aber so wunderbar vergleichen:

Code: Alles auswählen

            primzahlen = [3,5,7]
            for n in range(0,3):
                if not eingabe[n] is None:                      # überprüft ob Einträge richtig sind
                    if (float(lsg[n].replace(",", "."))) == float(eingabe[n]):
                        punkte += primzahlen[n]
                    else:
                        rueckmeldung.append(str(n+1) + ". Eintrag falsch, ")
                else:
                    rueckmeldung.append(str(n+1) + ". Eintrag leer, ")
(Wenn ihr wollt, erkläre ich auch die Idee mit den Primzahlen)
Benutzeravatar
Dennis89
User
Beiträge: 1152
Registriert: Freitag 11. Dezember 2020, 15:13

Hallo,

Zu deinem Problem, wie entsteht denn:

Code: Alles auswählen

[Decimal('3.6'), Decimal('4.8'), Decimal('6')]
?
Ist dass das 'Decimal' aus 'decimal'? Was soll es denn für ein Datentyp sein, wenn dich das stört? Wieso ist das Decimal wenn du es in deinem Vergleich in 'float' wandelst?

zu deinem Code: Wieso das 'range'? (0 ist der default-Wert, du kannst einfach 'range(3)' schreiben) Du könntest doch einfach über 'primzahlen' iterieren? Wenn du den Index unbedingt brauchst für die Prüfung von 'eingabe' dann kann dir 'enumerate' helfen.
Wobei man auch die Listen mit 'zip' verbinden könnte und für den Index in deiner 'rueckmeldung' könnte man enumerate noch verwenden. Dabei kannst du auch angeben, dass bei 1 anstatt bei 0 begonnen wird, dann spart du dir die +1.
Strings formatiert man eher mit 'f'-Strings.
Das könnte dann so aussehen:

Code: Alles auswählen

primzahlen = [3, 5, 7]
for index, (primzahl, eingabe, loesung) in enumerate(zip(primzahlen, eingaben, loesungen), 1):
    if eingabe is None:
        rueckmeldung.append(f'{index}. Eintrag leer')
    elif float(loesung.replace(",", ".")) == float(eingabe):
        punkte += primzahl
    else:
        rueckmeldung.append('f{index}. Eintrag falsch')


Grüße
Dennis

P.S. Sorry die vielen Rückfragen, habe dein ganzes Projekt nur am Rande verfolgt.
"When I got the music, I got a place to go" [Rancid, 1993]
Pitwheazle
User
Beiträge: 871
Registriert: Sonntag 19. September 2021, 09:40

Dennis89 hat geschrieben: Sonntag 12. Februar 2023, 22:08 Zu deinem Problem, wie entsteht denn:

Code: Alles auswählen

[Decimal('3.6'), Decimal('4.8'), Decimal('6')]
?
Das "Decimal" macht Django ganz alleine - hier:

Code: Alles auswählen

            if form.is_valid():  
                if protokoll.parameter["name"] == "tab":                            # für Wertetabellen
                    eingabe = []
                    eingabe.append(form.cleaned_data['y2'])
                    eingabe.append(form.cleaned_data['y3'])
                    eingabe.append(form.cleaned_data['y4'])
und das "Dezimal" kommt wahrscheinlich aus meinem forms.py:

Code: Alles auswählen

class AufgabeFormTab(forms.Form):
    y2 = forms.DecimalField(label='', max_digits=5,
                                decimal_places=2, required=False, localize=True, widget=forms.TextInput(attrs={'size': 3, 'autocomplete': 'off', 'autofocus': True,}))
    y3 = forms.DecimalField(label='', max_digits=5,
                                decimal_places=2, required=False, localize=True, widget=forms.TextInput(attrs={'size': 3, 'autocomplete': 'off'}))
    y4 = forms.DecimalField(label='', max_digits=5,
                                decimal_places=2, required=False, localize=True, widget=forms.TextInput(attrs={'size': 3, 'autocomplete': 'off'}))
Dennis89 hat geschrieben: Sonntag 12. Februar 2023, 22:08 Ist dass das 'Decimal' aus 'decimal'? Was soll es denn für ein Datentyp sein, wenn dich das stört? Wieso ist das Decimal wenn du es in deinem Vergleich in 'float' wandelst?
Nun ja, mit "float" erkennt er die Eingaben als richtig und ohne nicht.

Funktioniert ja auch prima. Ich kann auslesen, wieviele Eingaben richtig sind, welche falsch sind ...
Nur das Protokoll sieht blöd aus.
Benutzeravatar
Dennis89
User
Beiträge: 1152
Registriert: Freitag 11. Dezember 2020, 15:13

Und was wäre wenn du :

Code: Alles auswählen

eingabe.append(float(form.cleaned_data['y2']))
schreibst?
Dann könntest du das bei Vergleich weglassen.

Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Benutzeravatar
sparrow
User
Beiträge: 4184
Registriert: Freitag 17. April 2009, 10:28

Pitwheazle: Falls das hier noch nicht gesagt wurde: Du verwendest die Zeichenkettendarstellung von Listen und Objekten. Das tut man nicht. Nie.
Es gibt in Python die Konvention, dass die Ausgasbe entweder so ist, dass die man aus der Ausgabe ein identisches Objekt wieder erstellen kann (wie bei Listen, dicts oder auch Decimal) oder, wenn man das nicht kann, steht die Ausgabe in spitzen Klammern.

Wenn du also den Inhalt einer Liste ausgeben willst, dann musst _du_ für die Ausgabe sorgen.
Nochmal: Die Zeichenkettenrepresentation ist nicht dafür gedacht, dass du das irgendwo anzeigst. Aus eben diesen Gründen.

Code: Alles auswählen

>>> from decimal import Decimal
>>> eingabe = [Decimal('3.6'), Decimal('4.8'), Decimal('6')]
>>> ", ".join([str(e) for e in eingabe])
'3.6, 4.8, 6'
Ich bin übrigens auch hier der Meinung, dass dieses Ersetzen von Dezimaltrennern falsch ist.
Das sollte der Browser entscheiden. Und Django kann wunderbare lokalisieren und internationalisieren.

Und ich würde den umgekehrten Weg bei Vergleichen gehen. Nicht Decimal -> Float sondern was auch immer -> Decimal.

Code: Alles auswählen

from decimal import Decimal
>>> 0.1000000000000000055511151231257827021181583404541015625 == 0.1
True
>>> float(Decimal("0.1000000000000000055511151231257827021181583404541015625")) == 0.1
True
>>> Decimal("0.1000000000000000055511151231257827021181583404541015625") == Decimal("0.1")
False
Pitwheazle
User
Beiträge: 871
Registriert: Sonntag 19. September 2021, 09:40

sparrow hat geschrieben: Sonntag 12. Februar 2023, 22:42
Nochmal: Die Zeichenkettenrepresentation ist nicht dafür gedacht, dass du das irgendwo anzeigst. Aus eben diesen Gründen.
"Aus ebendiesen Gründen" heißt also soviel wie "macht man nicht".
Da muss ich mal drüber hirnen. In den Listen sind ja Zeichenfolgen, die müsste ich dann halt an der richtigen Stelle auspacken und neu zusammensetzen.

Code: Alles auswählen

>>> from decimal import Decimal
>>> eingabe = [Decimal('3.6'), Decimal('4.8'), Decimal('6')]
>>> ", ".join([str(e) for e in eingabe])
'3.6, 4.8, 6'
That's it!
Ich bin übrigens auch hier der Meinung, dass dieses Ersetzen von Dezimaltrennern falsch ist.
Das sollte der Browser entscheiden. Und Django kann wunderbare lokalisieren und internationalisieren.
Also mir ist es nicht gelungen, Kommazahlen ohne "replace" mit einem Komma darzustellen. Vielleicht fehlt mir da noch eine Info.
Und ich würde den umgekehrten Weg bei Vergleichen gehen. Nicht Decimal -> Float sondern was auch immer -> Decimal.
Auch prima!
Benutzeravatar
sparrow
User
Beiträge: 4184
Registriert: Freitag 17. April 2009, 10:28

Hier wie man Lokalisierung in Templates verwendet.
Wenn man Werte in Views lokalossieren möchte:

Code: Alles auswählen

>>> from django.utils import formats
>>> formats.localize(1.0, use_l10n=True)
'1,0'
Soweit ich weiß, kommt dann je nach Locale des Benutzers "." oder "," als Dezimaltrenner zurück.
Pitwheazle
User
Beiträge: 871
Registriert: Sonntag 19. September 2021, 09:40

Ich habe

Code: Alles auswählen

USE_L10N = True
in meinen settings.py eingetragen, das reicht eindeutig nicht.
Das:

Code: Alles auswählen

formats.localize(1.0, use_l10n=True)
sieht ja so aus, als müsste ich das bei jeder Ausgabe verwenden?
Benutzeravatar
sparrow
User
Beiträge: 4184
Registriert: Freitag 17. April 2009, 10:28

Django versucht automatisch die Ausgabe anzupassen.
Es kommt darauf an, was und wie du es im Template unterbringst.
Benutzeravatar
sparrow
User
Beiträge: 4184
Registriert: Freitag 17. April 2009, 10:28

Um das ein bisschen zu unterfüttern:

Wenn man so etwas in sein Template schreibt:

Code: Alles auswählen

Du hast {{ value }} eingegeben.
und value etwas ist, das lokalisiert werden kann, dann wird Django das lokalisieren. Es sei denn, man verhindert das.

Wäre value also Decimal("3.51"), dann würde dort imt deutscher Lokalisierung "Du hast 3,51 eingegeben" stehen. Ganz von alleine. So, wie es der Benutzer mit seiner Lokalisierung gewohnt ist.

Das kann aber natürlich nur funktionieren, wenn da etwas übergeben wird, worauf eine Lokalisierung angewendet werden kann.
Django kennt den "join"-Filter. Der funktioniert aber genau wie str.join() - operiert also auf Zeicheketten. Soweit mir bekannt verhindert das dann die Lokalisierung.
In deinem Fall würde also so etwas funktionieren:

Code: Alles auswählen

    raw_values = [Decimal('3.6'), Decimal('4.8'), Decimal('6')]
    values = [formats.localize(e) for e in raw_values]
Und dann kannst du in deinem Template den join-Filter verwenden:

Code: Alles auswählen

{{ values|join:", " }}
Pitwheazle
User
Beiträge: 871
Registriert: Sonntag 19. September 2021, 09:40

Danke, da muss ich erstmal drüber hirnen.
Das passt aber dann doch auch für @geraldfo viewtopic.php?t=56441
sparrow hat geschrieben: Montag 13. Februar 2023, 22:24 Um das ein bisschen zu unterfüttern:

Wenn man so etwas in sein Template schreibt:

Code: Alles auswählen

Du hast {{ value }} eingegeben.
und value etwas ist, das lokalisiert werden kann, dann wird Django das lokalisieren. Es sei denn, man verhindert das.
Wäre value also Decimal("3.51"), dann würde dort imt deutscher Lokalisierung "Du hast 3,51 eingegeben" stehen. Ganz von alleine. So, wie es der Benutzer mit seiner Lokalisierung gewohnt ist.
Dann hätte das eigentlich in den Anfängen meines Projektes auch schon funktionieren müssen, das muss ich nochmal nachprüfen (und möglicherweise einige "replace"s wieder rauswerfen)
geraldfo
User
Beiträge: 44
Registriert: Samstag 28. Januar 2023, 20:19
Wohnort: Nähe Wien

Vorschlag:
Wir könnten das Thema Lokalisierung projektunabhängig in einem eigenen Thread thematisieren.

Welche Anforderungen gibt es?
Welche Lösungen gibt es auf Browser-Ebene?
Welche Lösungen gibt es auf Django-Ebene?
Gibt es Probleme oder ist alles super?
Antworten