buchstaben aus einem string entfernen

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
Rinno
User
Beiträge: 2
Registriert: Samstag 16. Juni 2012, 14:54

hallo, liebe python gemeinde,
ich suche nach einer Möglichkeit alle Zahlen aus einem String, in meinem Fall ein md5 hash zu isolieren, und als neuen String abzuspeichern. Ich brauche das für einen Zufallsgenerator.

zb soll aus
"b59fa603913495a7650cf909e316d88b"
"59603913495765090931688"
werden.

Klingt einfach, ist es warscheinlich auch. Ich steige aber einfach nicht dahinter.

Ich benutze Python3 und mein bisheriger Ansatz war, den String erstmal in eine Liste umzuwandeln:

Code: Alles auswählen

hash=("b59fa603913495a7650cf909e316d88b")
list=list(hash)
um dann aus der Liste immer wieder mit

Code: Alles auswählen

if "a" in hash:
	hash.remove("a")
else:
	hash=hash
alle objekte mit dem buchstaben a Stück für Stück zu entfernen, und das mit lallen buchstaben von a bis z und am ende die Liste irgendwie wider in einen String zu verwandeln.

Aber das ist finde ich viel zu viel Code für ein so kleines Problem.
Und so richtig funktioniert mein Ansatz auch noch nicht. (ich bekomme keinen string mehr hin)
gibt es eine simplere methode?
Ich wäre echt froh eine zu finden, weil ich hänge hier schon seit einiger Zeit fest :/
Danke im Voraus
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Kleiner Tipp: ``str.isdigit`` existiert ;-) Zudem ``str.join``. Das kann man in einem Generatorausdruck schreiben...
Ansatz:

Code: Alles auswählen

"".<method>(<Test> for c in hash)
"<method>" und "<Test>" musst Du nun mit den beiden genannten Tipps umsetzen.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
snafu
User
Beiträge: 6908
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Code: Alles auswählen

import re
hash = "b59fa603913495a7650cf909e316d88b"
re.sub("\d+", "", hash) # => 'bfaacfedb'
`"\d+"` findet alle in `hash` enthaltenen Ziffernfolgen (Digits), wobei das `+` für die Bedingung "ein oder mehrere" steht. Auf jede Fundstelle wird das zweite Argument (hier: leerer String) zur Ersetzung angewendet. `hash` selbst ist schließlich die Zeichenkette, auf welcher die Ersetzungen ausgeführt werden sollen.

Übrigens klappt ein `"\d"` in diesem Fall genau so. Allerdings würde die Ersetzung dann theoretisch für jede Ziffer einzeln angewendet werden, was zu schlechterer Laufzeit führen dürfte. Mögliche interne Optimierungen, die möglicherweise in dem hinter `re.sub()` "liegenden" Code stattfinden, lasse ich mal bewusst außen vor, da diese nicht garantiert sind. Diese Anmerkung spielt prinzipiell auch nur eine Rolle in der Praxis (im Sinne von spürbar schlechterer Laufzeit), wenn man es mit größeren Texten zu tun hat (trifft bei Hashwerten wohl eher weniger zu). Andererseits sollte man IMHO auch solche Sachen von Anfang an "korrekt" machen. :)

Achso, und eigentlich ist dein Thread eher ein Thema für das Forum "Allgemeine Fragen". Vielleicht für's nächste Mal beachten... ;)

EDIT: Und falls man reguläre Ausdrücke vermeiden möchte, geht's natürlich auch "zu Fuß" in reinem Python:

Code: Alles auswählen

"".join(char for char in hash if char.isalpha())
Rinno
User
Beiträge: 2
Registriert: Samstag 16. Juni 2012, 14:54

Danke euch beiden für eure hilfe :)
snafu hat mich auf den richtigen weg gebracht. =D

Code: Alles auswählen

import re
re.sub("[^0-9]", "", hash)
ersetzt meinen Din a4 seiten langen code zuferlässig :D
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Ich bevorzuge da ja den Weg, den Hyperion aufgezeigt hat:

Code: Alles auswählen

In [4]: hash = "b59fa603913495a7650cf909e316d88b"

In [5]: ''.join(c for c in hash if c.isdigit())
Out[5]: '59603913495765090931688'
Und mit filter:

Code: Alles auswählen

In [6]: filter(operator.methodcaller('isdigit'), hash)
Out[6]: '59603913495765090931688'
Benutzeravatar
snafu
User
Beiträge: 6908
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Oder hier: Auch mit `filter()` aber ohne `methodcaller()`:

Code: Alles auswählen

filter(lambda c: c.isalpha(), hash)
Man sieht schon: "There should be only one preferred way to do it..." (oder so ähnlich) :mrgreen:

EDIT: Ups. jetzt merk ich erstmal, dass ich die ganze Zeit das Gegenteil mache. Es sollen ja die *Buchstaben* entfernt werden. :oops:
Benutzeravatar
snafu
User
Beiträge: 6908
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Rinno hat geschrieben:

Code: Alles auswählen

import re
re.sub("[^0-9]", "", hash)
Dafür gibt's übrigens ne kürzere Lösung:

Code: Alles auswählen

re.sub("\D+", "", hash)
Das ersetzt alle "Nicht-Digits".
BlackJack

Ebenfalls ein Ansatz wäre die `translate()`-Methode auf Zeichenketten.
Benutzeravatar
/me
User
Beiträge: 3561
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

BlackJack hat geschrieben:Ebenfalls ein Ansatz wäre die `translate()`-Methode auf Zeichenketten.
Und der beste Ansatz wäre es, einen bestehenden Zufallszahlengenerator zu verwenden. :mrgreen:
Benutzeravatar
snafu
User
Beiträge: 6908
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

/me hat geschrieben:Und der beste Ansatz wäre es, einen bestehenden Zufallszahlengenerator zu verwenden. :mrgreen:
Du hinterfragst den Sinn von User-Anfragen? :o
Benutzeravatar
/me
User
Beiträge: 3561
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

snafu hat geschrieben:Du hinterfragst den Sinn von User-Anfragen? :o
Das ist wie üblich Hilfe zur Selbsthilfe. Der Fragesteller sollte sich darüber klar sein was er da tut. Ich weiß nicht, ob ihm alle Auswirkungen dieses Ansatzes klar sind, wie zum Beispiel eine extreme Ungleichverteilung von Zahlen. Eine 1 wird deutlich seltener als Ergebnis herauskommen als beispielsweise eine 111
Benutzeravatar
snafu
User
Beiträge: 6908
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Naja, wenn einfach nur Zufallszahlen gebraucht werden, dann ist die Empfehlung natürlich random.randint():

Code: Alles auswählen

[random.randint(0, 9) for _ in xrange(30)]
...generiert 30 zufällige Zahlen zwischen 0-9.
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

snafu hat geschrieben:Naja, wenn einfach nur Zufallszahlen gebraucht werden, dann ist die Empfehlung natürlich random.randint():

Code: Alles auswählen

[random.randint(0, 9) for _ in xrange(30)]
...generiert 30 zufällige Zahlen zwischen 0-9.
Und `join` um daraus einen String zu machen:

Code: Alles auswählen

''.join(random.randint(0, 9) for _ in xrange(30))
the more they change the more they stay the same
BlackJack

Wobei man bei diesen Zeichenketten auch wieder aufpassen muss, dass man keine gleichmässige Verteilung hat, wenn man sie als Zahlen auffasst. Irgend so etwas wird Rinno ja wahrscheinlich vorhaben, wenn er die Ziffern irgend wo heraus filtert.

Das klingt sowieso komisch aus einem Hash-Wert in Hexadezimal-Schreibweise nur die Ziffern heraus zu fischen, die auch in Dezimaldarstellungen gültig wären. Warum möchte man auf diese Weise 128 Bit-Werte ungleichmässig verteilt auf einen ≈106,3 Bit Wertebereich abbilden‽
Antworten