Seite 1 von 2
strip, split - mehrere Argumente
Verfasst: Freitag 9. Juli 2010, 17:11
von Yuzuke
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?
Re: strip, split - mehrere Argumente
Verfasst: Freitag 9. Juli 2010, 17:15
von lunar
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.
Re: strip, split - mehrere Argumente
Verfasst: Freitag 9. Juli 2010, 17:54
von Dav1d
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']]
Re: strip, split - mehrere Argumente
Verfasst: Freitag 9. Juli 2010, 19:52
von karolus
Hallo
Code: Alles auswählen
import re
vstring = "3V4+3"
re.findall( "\d+" , vstring)
Gruß Karo
Re: strip, split - mehrere Argumente
Verfasst: Samstag 10. Juli 2010, 09:05
von Yuzuke
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.
Re: strip, split - mehrere Argumente
Verfasst: Samstag 10. Juli 2010, 09:19
von karolus
Re: strip, split - mehrere Argumente
Verfasst: Samstag 10. Juli 2010, 09:19
von b.esser-wisser
Yuzuke hat geschrieben:Folgende Formen kann das ganze nämlich annehmen:
2V17+3
5V2
12V8-3
19V19+100
Könntest du erklären, was das ist?
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
"""
edit: regex vereinfacht, ps geschrieben
Re: strip, split - mehrere Argumente
Verfasst: Samstag 10. Juli 2010, 09:45
von hendrikS
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.
Re: strip, split - mehrere Argumente
Verfasst: Samstag 10. Juli 2010, 11:56
von sma
b.esser-wisser hat geschrieben:ps.: Sind 'verbose'-Regex viel besser lesbar?
Nein. Ich finde die kompakte Form übersichtlicher. Aber das war wohl eine rhetorische Frage, oder?
Stefan
Re: strip, split - mehrere Argumente
Verfasst: Samstag 10. Juli 2010, 12:13
von lunar
sma hat geschrieben:b.esser-wisser hat geschrieben:ps.: Sind 'verbose'-Regex viel besser lesbar?
Nein. Ich finde die kompakte Form übersichtlicher.[/quote]
Naja, es kommt irgendwo auch auf die Komplexität des Ausdrucks an ...
Re: strip, split - mehrere Argumente
Verfasst: Samstag 10. Juli 2010, 13:50
von HerrHagen
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
Re: strip, split - mehrere Argumente
Verfasst: Montag 19. Juli 2010, 11:54
von Yuzuke
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:
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
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?
Re: strip, split - mehrere Argumente
Verfasst: Montag 19. Juli 2010, 12:01
von Hyperion
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.
Re: strip, split - mehrere Argumente
Verfasst: Montag 19. Juli 2010, 13:26
von Trichter
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)
Re: strip, split - mehrere Argumente
Verfasst: Montag 19. Juli 2010, 17:04
von pillmuncher
Zum Spaß:
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!!!')
Gruß,
Mick.
Re: strip, split - mehrere Argumente
Verfasst: Montag 19. Juli 2010, 17:13
von sma
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
Re: strip, split - mehrere Argumente
Verfasst: Dienstag 20. Juli 2010, 00:40
von Shaldy
Ähhh, hab ich das Problem nicht verstanden oder habt ihr alle einfach nur Spaß an ellenlangem Code?
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")
Ungetestet
Re: strip, split - mehrere Argumente
Verfasst: Dienstag 20. Juli 2010, 00:59
von pillmuncher
Shaldy hat geschrieben:Ähhh, hab ich das Problem nicht verstanden oder habt ihr alle einfach nur Spaß an ellenlangem Code?
Deiner ist ca. 2/3 von meinem. Dafür hast du keine Fehlerbehandlung. Außerdem addierst du den Zusatz sogar wenn '-' davor steht.
Gruß,
Mick.
Re: strip, split - mehrere Argumente
Verfasst: Dienstag 20. Juli 2010, 08:27
von EyDu
Shaldy hat geschrieben:Ähhh, hab ich das Problem nicht verstanden oder habt ihr alle einfach nur Spaß an ellenlangem Code?
Das selbe könnte man dich fragen
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)))
Die Fehler und schlechten Namen habe ich einfach mal belassen.
Re: strip, split - mehrere Argumente
Verfasst: Dienstag 20. Juli 2010, 09:23
von Shaldy
Schont gut, schon gut...