Hallo,
ich möchte die Zeichenkette "3V4+3" oder "2V1-5" aufteilen, dass ich jeweils die Zahlen in einer Liste habe. Im ersten Fall möchte ich also Liste[3,4,3] im zweiten Liste=[2,1,5]. Das ganze habe ich mit strip und split versucht, allerdings geht das nicht. Was soll ich machen?
strip, split - mehrere Argumente
Was Du erst mal machen sollst, ist uns sagen, wie Dein Versuch aussah, und was nicht funktioniert hat
In einem Schritt lässt sich das mit ".split()" und ".strip()" eh nicht trennen. Das würde nur mit einem regulären Ausdruck und "re.split" funktionieren.
In einem Schritt lässt sich das mit ".split()" und ".strip()" eh nicht trennen. Das würde nur mit einem regulären Ausdruck und "re.split" funktionieren.
Dein Problem könnte man gut mit einer List Comprehension lösen:
Code: Alles auswählen
>>> l = ['3V4+3', '2V1-5']
>>> [[c for c in item if c.isdigit()] for item in l]
[['3', '4', '3'], ['2', '1', '5']]
the more they change the more they stay the same
Hallo
Gruß Karo
Code: Alles auswählen
import re
vstring = "3V4+3"
re.findall( "\d+" , vstring)
Hmm, danke für eure Hilfe. Ich habe gerade gemerkt, dass es noch ein wenig komplizierter ist.
Folgende Formen kann das ganze nämlich annehmen:
2V17+3
5V2
12V8-3
19V19+100
Die Zahlen können also beliebe Werte annehmen, während der Teil mit + und - zuzüglich der Zahl danach nicht vorkommen muss, aber kann. Außerdem muss ich schon wissen, ob es sich um ein + oder - handelt. Wenn ich re.findall( "\d+" , vstring) benutze, bekomme ich ja nur die Zahlen, + und - aber nicht. Wenn ich [c for c in vstring] benutze, habe ich allerdings keine Ahnung wo sich das + oder - befindet (kann ja an unterschiedlichen Stellen sein, da die Zahlen unterschiedlich lang sein können) und ich kann dann nicht z.B. if Variable[3] == "+": abfragen.
Folgende Formen kann das ganze nämlich annehmen:
2V17+3
5V2
12V8-3
19V19+100
Die Zahlen können also beliebe Werte annehmen, während der Teil mit + und - zuzüglich der Zahl danach nicht vorkommen muss, aber kann. Außerdem muss ich schon wissen, ob es sich um ein + oder - handelt. Wenn ich re.findall( "\d+" , vstring) benutze, bekomme ich ja nur die Zahlen, + und - aber nicht. Wenn ich [c for c in vstring] benutze, habe ich allerdings keine Ahnung wo sich das + oder - befindet (kann ja an unterschiedlichen Stellen sein, da die Zahlen unterschiedlich lang sein können) und ich kann dann nicht z.B. if Variable[3] == "+": abfragen.
Hallo
Gruß Karo
Code: Alles auswählen
re.findall("(?:\+|-)?\d+", vstring)
- b.esser-wisser
- User
- Beiträge: 272
- Registriert: Freitag 20. Februar 2009, 14:21
- Wohnort: Bundeshauptstadt B.
Könntest du erklären, was das ist?Yuzuke hat geschrieben:Folgende Formen kann das ganze nämlich annehmen:
2V17+3
5V2
12V8-3
19V19+100
Diese Beispiele kann man ja noch mit regex abdecken: "(\d+)V(\d+)([+-]\d+)?" (ungestet)
hth, Jörg
ps.: Sind 'verbose'-Regex viel besser lesbar?
Code: Alles auswählen
r"""(?x) #verbose regex
( #Neue Gruppe
\d+ #mehr als 1 Ziffer
) # 1. Gruppe (<matchobject>.group(1)
V # ein 'V'
(
\d+
) # 2. Gruppe
(
[+-] # '+' oder '-'
\d+
)? # 3. Gruppe, ist optional
"""
Eigentlich ist das doch eine schöne Übung und auch kein Hexenwerk.
Du legst eine leere Liste an. Dann iterierst Du über den String. Wenn das aktuelle Zeichen ein Digit ist fügst Du es einem aktuellen Ziffernstring hinzu. Wenn dann mal was anderes als eine Ziffer kommt, hängst Du diesen einfach an die Liste an. Mal ausprobieren. Es ist viel schöner, wenn man ein Problem selbst geknackt hat. Wenn's hakt gibt es sicher genügend, die weiterhelfen können.
In der Snippets Sektion gibt es ausserdem auf der zweiten Seite ganz oben ein paar Beispiele zu einem ähnlich gestrickten Problem.
Du legst eine leere Liste an. Dann iterierst Du über den String. Wenn das aktuelle Zeichen ein Digit ist fügst Du es einem aktuellen Ziffernstring hinzu. Wenn dann mal was anderes als eine Ziffer kommt, hängst Du diesen einfach an die Liste an. Mal ausprobieren. Es ist viel schöner, wenn man ein Problem selbst geknackt hat. Wenn's hakt gibt es sicher genügend, die weiterhelfen können.
In der Snippets Sektion gibt es ausserdem auf der zweiten Seite ganz oben ein paar Beispiele zu einem ähnlich gestrickten Problem.
Nein. Ich finde die kompakte Form übersichtlicher.[/quote]sma hat geschrieben:b.esser-wisser hat geschrieben:ps.: Sind 'verbose'-Regex viel besser lesbar?
Naja, es kommt irgendwo auch auf die Komplexität des Ausdrucks an ...
Zuletzt geändert von lunar am Sonntag 11. Juli 2010, 11:02, insgesamt 1-mal geändert.
Mann kann sich ja auch eine nicht kommentierte RE kommentieren lassen:
Code: Alles auswählen
>>> re.compile("(?:\+|-)?\d+", re.DEBUG)
max_repeat 0 1
subpattern None
in
literal 43
literal 45
max_repeat 1 65535
in
category category_digit
Hallo,
danke an alle, ich habe es jetzt hinbekommen wenn auch nicht mit RegEx, sondern mit der Standardfunktion find(). Da sich nochmal ein paar Sachen geändert haben und falls vllt. andere an dieser Lösung interessiert sind poste ich sie mal:
Zur Erklärung: In einem Spiel namens Midgard wird der Schaden, den ein Held anrichtet auf die oben beschriebene Weise beschrieben. 2W6+5 bedeutet nichts anderes als 2 mal mit einem 6 seitigem Würfel zu würfeln und 5 zu addieren - fertig ist der Schaden. Genau das soll mein Code abarbeiten. Ich weiß ich bin ein Python Anfänger und es gibt sicherlich bessere Möglichkeiten aber so geht's doch, oder?
danke an alle, ich habe es jetzt hinbekommen wenn auch nicht mit RegEx, sondern mit der Standardfunktion find(). Da sich nochmal ein paar Sachen geändert haben und falls vllt. andere an dieser Lösung interessiert sind poste ich sie mal:
Code: Alles auswählen
String = "2W6+5"
Damage = 0
if String.find("+") >= 0:
Modifier = "+"
Until = String.find("+")
Left = String[0:Until]
Number = int(String[Until+1:])
String = String[0:Until]
elif String.find("-") >= 0:
Modifier = "-"
Until = String.find("-")
Left = String[0:Until]
Number = int(String[Until+1:])
String = String[0:Until]
else:
Modifier = None
Until = String.find("W")
Counter = int(String[0:Until])
Dice = int(String[Until+1:])
for i in range(Counter):
Damage += random.randint(1,Dice)
if Modifier is not None:
if Modifier == "+":
Damage += Number
if Modifier == "-":
Damage -= Number
if Damage < 0:
Damage = 0
return Damage
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Alternativ kann man ggf. auch das benutzen: http://code.google.com/p/dyce/
Ich würde bei dieser simplen Form wohl auch mit einem RegExp arbeiten.
Ich würde bei dieser simplen Form wohl auch mit einem RegExp arbeiten.
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
Zufällig komme ich auch aus der RPG Ecke und hab da was für dich:
Code: Alles auswählen
import random
def roll_dice(a,b):
result = 0
for i in range(a):
result += random.randint(1,b)
return result
def eval_number(input_string):
try:
result = int(input_string)
except ValueError:
dice_list = input_string.split("W")
result = roll_dice(int(dice_list[0]), int(dice_list[1]))
return result
def eval_term(input_string):
input_string.strip()
result = 0
plus_list = input_string.split('+')
for p_term in plus_list:
minus_list = p_term.split('-')
# evaluate first term of minus_list
result += eval_number(minus_list[0])
# evaluate other terms of minus list
for i in range(1, len(minus_list)):
result -= eval_number(minus_list[i])
return max(result, 0)
test = ["2W6+3", "5-3", "18W20-5", "5+3-8", "1W6-12"]
for element in test:
print eval_term(element)
- pillmuncher
- User
- Beiträge: 1484
- Registriert: Samstag 21. März 2009, 22:59
- Wohnort: Pfaffenwinkel
Zum Spaß:
Gruß,
Mick.
Code: Alles auswählen
import re
import random
import operator
class Bunch(object):
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
match = re.compile(
flags = re.VERBOSE,
pattern = r"""
(?P<times> \d+ )
(?P<item> [A-Z] )
(?P<sides> \d+ )
( (?P<op> \+ | \- ) (?P<value> \d+ ) | $ )
| (?P<error> .* )
"""
).match
ops = {'+':operator.add, '-':operator.sub, None:operator.add}
def damage(raw):
parsed = Bunch(**match(raw).groupdict())
if parsed.error:
raise ValueError('Invalid argument "%s"' % parsed.error)
times = int(parsed.times)
sides = int(parsed.sides)
value = int(parsed.value or 0)
op = ops[parsed.op]
return max(0, op(sum(random.randint(1, sides) for each in xrange(times)), value))
print damage('2W6+5')
print damage('1W6-7') # immer 0
print damage('2V17+3')
print damage('5V2')
print damage('12V8-3')
print damage('19V19+100')
print damage('hallo ich bin kaputt!!!')
Mick.
Zuletzt geändert von pillmuncher am Dienstag 20. Juli 2010, 00:50, insgesamt 2-mal geändert.
In specifications, Murphy's Law supersedes Ohm's.
Ich weiß ja nicht, ob es wirklich ums Würfeln geht, aber 2008 hatte ich mal http://python-forum.de/viewtopic.php?p=114705 implementiert.
Stefan
Stefan
Ähhh, hab ich das Problem nicht verstanden oder habt ihr alle einfach nur Spaß an ellenlangem Code?
Ungetestet
Code: Alles auswählen
import random
def Damage(wurfzahl, seitenzahl, zusatz):
erg = 0
for x in range(wurfzahl):
erg += random.randint(1, seitenzahl + 1) #kA ob das so richtig ist, jedenfalls soll eine Zahl "auf dem Würfel" gewählt werden...
erg += zusatz
return erg
def StringDamage(string):
temp = string.split("W")
if "+" in temp[1]:
temp2 = temp[1].split("+")
else:
temp2 = temp[1].split("-")
wurfzahl = int(temp[0])
seitenzahl = int(temp2[0])
zusatz = int(temp2[1])
return Damage(wurfzahlm seitenzahl, zusatz)
if __name__ == "__main__":
print Damage(3, 6, -4)
print Damage(4, 18, 22)
print StringDamage("3W12-9")
print StringDamage("2W6+8")
Dies ist keine Signatur!
- pillmuncher
- User
- Beiträge: 1484
- Registriert: Samstag 21. März 2009, 22:59
- Wohnort: Pfaffenwinkel
Deiner ist ca. 2/3 von meinem. Dafür hast du keine Fehlerbehandlung. Außerdem addierst du den Zusatz sogar wenn '-' davor steht.Shaldy hat geschrieben:Ähhh, hab ich das Problem nicht verstanden oder habt ihr alle einfach nur Spaß an ellenlangem Code?
Gruß,
Mick.
In specifications, Murphy's Law supersedes Ohm's.
Das selbe könnte man dich fragenShaldy hat geschrieben:Ähhh, hab ich das Problem nicht verstanden oder habt ihr alle einfach nur Spaß an ellenlangem Code?
Code: Alles auswählen
import random
import re
def damage(wurfzahl, seitenzahl, zusatz):
return zusatz + sum(random.randint(1, seitenzahl + 1)
for _ in range(wurfzahl))
def string_damage(s):
wurfzahl, temp = s.split("W")
seitenzahl, zusatz = re.split("[+-]", temp)
return damage(*map(int, (wurfzahl, seitenzahl, zusatz)))
Das Leben ist wie ein Tennisball.