Zeichenkette in Zahl auflösen

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
jake-the-snake

Hallo Forum

Wenn ich in einem Programm "Hallo" einlese, ergibt dies nach einer Bearbeitungsroutine folgenden String:
[codebox=bash file=Unbenannt.bsh]72~97~108~108~111~[/code]
Ich möchte das für Testzwecke zurück-codieren.
Da die Textlänge unbekannt ist, könnte ich jetzt die "~" Separatoren zählen und dann weiss ich, wieviel Zeichen der Text enthält.
Das Problem bei diesem Text-String ist, dass der Bereich vor einem Separator zwei- oder dreistellig sein kann. Und für die chr(x)- Funktion
brauche ich ja zwingend Numerische Zahlen - keine Text-Zahlen.

Meine Idee wäre jetzt, irgendwie mit if-Anweisung abzuklären, ob der Bereich zwischen den "~" 2- oder 3-stellig ist?
Oder gibt es noch eine andere Möglichkeit, nur an die Zahlen zu kommen?
Also quasi:
[codebox=bash file=Unbenannt.bsh]
72
97
108
108
111[/code]
Nach jedem Schleifendurchlauf einzeln?

Gruß jts
Benutzeravatar
noisefloor
User
Beiträge: 3853
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,
Oder gibt es noch eine andere Möglichkeit, nur an die Zahlen zu kommen?
Ja, sicher. String-Objekte kennen die Methode `split`. Damit bist du so gut wie am Ziel.

Gruß, noisefloor
jake-the-snake

Hallo Forum / Hi noisefloor :wink:


Ausgangswert:
[codebox=text file=Unbenannt.txt]72~97~108~108~111~[/code]
Der Code:

Code: Alles auswählen

        # Auftrennung 
        cryptocode = cryptocode.split('~')
        print (cryptocode)
Im Terminal ergibt ein Testausdruck:
[codebox=bash file=Unbenannt.bsh]['72', '97', '108', '108', '111', ''][/code]
In der Textbox von tkinter dies:
[codebox=text file=Unbenannt.txt]72 97 108 108 111 {}[/code]

Der Inhalt der gleichen Variable "cryptocode" ergibt im Terminal etwas anderes als in der Textbox von tkinter.
Wenn ich so mit Perl vergleiche, sieht es jetzt fast so aus, als ob der nun ein array aus meiner Variable gestrickt hat?

Gruß und Dank an noisefloor

jts
Benutzeravatar
Kebap
User
Beiträge: 687
Registriert: Dienstag 15. November 2011, 14:20
Wohnort: Dortmund

jake-the-snake hat geschrieben: Wenn ich so mit Perl vergleiche, sieht es jetzt fast so aus, als ob der nun ein array aus meiner Variable gestrickt hat?
Sieht so ähnlich aus, yo.
Du wärst aber gut beraten, statt von anderen Sprachen auf Python zu schließen, und dich von Vermutung zu Vermutung zu hangeln, stattdessen ein Tutorial für die Grundlagen von Python zu lesen. Da lernt man recht früh solche String-Bearbeitung und auch diese elementare Datentypen wie Listen (du nennst es array) und Wörterbücher, und was man damit anstellen kann. Das mit den Vermutungen passiert ja quasi zwangsläufig nebenbei, aber als einzige Grundlage wäre es zu wenig.

Zum Test kannst du machen: print(type(cryptocode))
MorgenGrauen: 1 Welt, 8 Rassen, 13 Gilden, >250 Abenteuer, >5000 Waffen & Rüstungen,
>7000 NPC, >16000 Räume, >200 freiwillige Programmierer, nur Text, viel Spaß, seit 1992.
Benutzeravatar
noisefloor
User
Beiträge: 3853
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

`split` liefert eine Liste des "verbleibenden" Textes zurück. Das ist das, was du im Terminal (richtigerweise) siehst.

Was Tkinter macht, wenn man eine Liste in eine Textbox packt, kann ich dir nicht sagen. Scheinbar findet da in irgendeiner Form eine Umwandlung bzw. Auflösung der Liste statt?

Abgesehen davon macht es hier so wie so wenig Sinn, eine Liste auszugeben - das ist ja nur der Zwischenschritt. Die willst doch am Ende Klartext, d.h. es folgenden noch zwei Operationen:
* Umwandlung der Strings in eine Zahl
* anwenden von `chr()`

Das geht z.B. mit 2x map oder einer List Comprehension, beides kombiniert mit einem `join`.

Gruß, noisefloor
jake-the-snake

Hallihallo 8)

Der Codeschnipsel, wobei Zeile 4-7 zur Testphase gehören (hab ich auskommentiert):

Code: Alles auswählen

# Einzelwerte aus Liste heraustrennen
        for element in cryptocode:
            singlesign = element.split(" ")
            # singlesign = ''.join(singlesign)
            # singlesign = (str.replace("[", ""))
            # singlesign.replace("]", "")
            # singlesign.replace("'", "")
            print (singlesign)
            # Variable singlesign mit sich selbst verlängern und in eine neue Kette verwandeln
            # singlechain = str(singlechain) + singlesign
        # Zusammengesetzte Zeichen ausgeben
        print (singlechain)
Bis Zeile 8 funktioniert es. Er druckt mir halt für die möchte-gern Variable "singlesign" ein einzelnes Listenelement z. B. ['72'] aus. An der Stelle bräuchte ich aber den Wert 72!

Wenn ich jetzt das einzelne Listenelement noch in einen sauberen String bekomme - dann hab ich es geschafft. Wie man sieht, habe ich versucht,
mittels replace() die eckigen Klammern ([]) und Apostrophe(' ') weg zu bekommen - quasi mit der Brechstange - ohne Erfolg :(

Gruß jts
Benutzeravatar
noisefloor
User
Beiträge: 3853
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,
quasi mit der Brechstange
Und so was von falsch... Da fehlen sämtliche Grundlagen, weil du nicht mal im Ansatz weißt, dass du da tust. Die eckigen Klammern gehören halt zu Liste bzw. kennzeichnen die Liste als solche. Abhilfe: endlich mal das Python-Tutorial lesen.

Damit du z.B. auch das hier verstehst:

[codebox=pycon file=Unbenannt.txt]>>> text = '72~97~108~108~111~'
>>> result = ''.join([chr(int(x)) for x in text.rstrip('~').split('~')])
>>> print(result)
Hallo
>>>[/code]

Gruß, noisefloor
jake-the-snake

Hallo

Glaubst du die Python-Befehle saug' ich mir aus den Fingern?
Ich hab ein PDF-Tutorial (Deutsch) und noch zwei-drei Internet-Tutorials (Englisch) gleichzeitig offen.
Ich mach nichts anderes als zu versuchen, aus diesen Dingern schlau zu werden.
Das ist einfach unangemessen, mir ständig vorzuhalten, ich würde nicht ins Tutorial blicken.
Dem ist nicht so!

Und die Zeilen 4-7 sind "syntaktisch" nicht richtig, weil die vom Testen verändert wurden. Ich habe sie nur auf die Schnelle auskommentiert.

Gruß jts

PS. Ich komme nicht von der Uni - bin normalsterblicher!
Benutzeravatar
noisefloor
User
Beiträge: 3853
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

es gibt bergeweise schlechte Tutorials zu Python im Netz. Problematisch für dich als Anfänger: du kannst halt nicht unterscheiden, was gut und schlecht ist. Liegt in der Natur der Sache.
Darum kommt hier im Forum auch so gut wie immer der Hinweis: lest das offizielle Python-Tutorial (weil: das ist gut!). Korrigiere mich, wenn es nicht stimmt, aber AFAIK hast du das noch nicht durchgearbeitet.
Glaubst du die Python-Befehle saug' ich mir aus den Fingern?
Nein, aber der Code zeigt, dass du nicht verstehst, was da passiert. Programmieren ist nicht raten.
Und die Zeilen 4-7 sind "syntaktisch" nicht richtig,
Das ist auch ziemlich Latte, weil das grundsätzliche Vorgehen, also deine "Idee", dass zu "lösen", 110% falsch ist. Es zeigt lediglich, dass du dir dringend Wissen der grundlegenden Datenstrukturen von von Python (String, Zahlen, Listen, Tuple, Dictionary) aneignen solltest.
Ich komme nicht von der Uni - bin normalsterblicher!
Ich habe weder vom Studium her noch beruflich was mit IT am Hut (auf der Uni habe ich noch einen HP-48G benutzt :-) ). Was wir hier diskutieren hat auch so rein gar nichts akademisches, dass ist des Python-Programmieres tägliches Handwerkszeug.

Du hast ja das Ziel, ein bestimmtest Programm mit GUI für den Raspi zu schreiben. Da wirst du mit Copy&Paste aus Tutorials und ein paar Fragen hier im Forum (und anderen Supportforen...) nie nie nie niemals hinkommen. Im Moment hängst du an der korrekten Darstellung der Elemente einer Liste als String. Sagen wir mal, das funktioniert irgendwann, weil das ein triviales Problem ist. Im nächsten Schritt kommt dann das Reagieren auf Events (z.B. Texteingabe) in der GUI. Und allerspätestens dann solltest du tunlichst die in vielen Post besagte Objektorientierung verstanden haben und verstanden haben, wie Callback-Funktionen funktionieren, weil der Programmablauf dann komplett nicht linear sein kann.

Kurz: wenn dir was an deinem Ziel liegt, dann hör' endlich auf, dir per C&P Code zusammen zuraten und eigne dir _vernünftig_ die notwendigen Grundlagen an.

Gruß, noisefloor
sebastian0202
User
Beiträge: 168
Registriert: Montag 9. Mai 2016, 09:14
Wohnort: Berlin

Hallo,


mit dem modul re und der findall Funktion geht es auch.

Code: Alles auswählen

import re
text = '72~97~108~108~111~32~87~101~108~116'
zahlen = re.findall(r"([0-9]{1,3})", text)

def zahlen_zu_text(zahlen):
    zeichen = [chr(int(x)) for x in zahlen]
    return ''.join(zeichen)

def text_zu_zahlen(text):
    zahlen = [str(ord(x)) for x in text]
    zahlen_text = "~".join(zahlen)
    return "%s~" % zahlen_text

print(zahlen_zu_text(zahlen))
#Hallo Welt
print(text_zu_zahlen("Hallo Welt"))
#72~97~108~108~111~32~87~101~108~116

Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

@jake-the-snake: wichtig beim Lernen von Python (und jeder anderen Programmiersprache auch) ist es, nicht zu denken, man wüßte schon, wie alles geht weil man schon eine andere Programmiersprache (Perl) kennt, sondern man muß sich auf die neue Sprache einlassen. Dazu hilft, das offizielle Tutorial zu lesen, und dann z.B. bei Strings nochmal genauer dessen Methoden anschauen.

Wobei man das Problem mit Perl ganz ähnlich löst:
[codebox=perl file=Unbenannt.pl]
$txt = "72~97~108~108~111~";
$res = join('', map(chr, split(/~/, $txt)));
print "$res\n";
[/code]

@sebastian0202: reguläre Ausdrücke sind dafür da, Muster zu extrahieren. Das Muster hier ist aber die Trennung von Zahlen durch `~`.

Die Annahme, dass es nicht größere Zeichencodes als 999 gibt, ist übrigens falsch.
sebastian0202
User
Beiträge: 168
Registriert: Montag 9. Mai 2016, 09:14
Wohnort: Berlin

Hallo,



wollte ja nur eine weitere Möglichkeit zeigen, auch wenn ganz klar split bei diesem Fall zum Einsatz kommen sollte.
Ich hab echt angenommen, dass 999 Zeichen genug sind.
In Python 2 begrenzte sich der range auf 256 mögliche Werte.
https://docs.python.org/2/library/functions.html#chr
chr(i)
Return a string of one character whose ASCII code is the integer i. For example, chr(97) returns the string 'a'. This is the inverse of ord(). The argument must be in the range [0..255], inclusive; ValueError will be raised if i is outside that range. See also unichr().
Ich sehe aber gerade, dass in Python 3 viel mehr möglich sind.
https://docs.python.org/3/library/functions.html#chr
chr(i)
Return the string representing a character whose Unicode code point is the integer i. For example, chr(97) returns the string 'a', while chr(8364) returns the string '€'. This is the inverse of ord().
The valid range for the argument is from 0 through 1,114,111 (0x10FFFF in base 16). ValueError will be raised if i is outside that range.
Dann halt eben das: :lol:

Code: Alles auswählen

# re.findall(r"([0-9]+)", text)
__deets__
User
Beiträge: 14522
Registriert: Mittwoch 14. Oktober 2015, 14:29

Und wenn alle Stricke reißen: http://search.cpan.org/dist/Tk/pod/UserGuide.pod - auch Perl kann guis mit tk.
jake-the-snake

Abend Forum

Danke für die vielen Beispiele.

Den Ausdruck von noisefloor ...

Code: Alles auswählen

result = ''.join([chr(int(x)) for x in text.rstrip('~').split('~')])
... habe ich verwendet, weil ich da noch eher durchblicke - und er war gut abwandelbar, da er Einzelroutinen enthält
(die x-loop) und ich somit entsprechende, weitere Verarbeitung durchführen konnte.

Das Programm läuft auch schon beinahe - eine "Kleinigkeit" muss ich noch hinbekommen - dann bin ich fertig.
Codieren geht und ist zukünftig ausbaufähig, von USB schreiben und lesen geht, die Textfelder funktionieren ebenfalls für Eingabe und Ausgabe.
Alles wunderbar!

Nochmals Danke für die Hilfe und Hilfestellungen :)

Gruß jts

PS. Ich bin vom Lerntyp eher der, der sich das gerade bei Bedarf aneignet. Das berühmte "learnig by doing".
(Geht freilich nicht überall -> Bei Arbeiten an der Gastherme beispielsweise - ganz schlecht! :D )
Antworten