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
Hallo

Code: Alles auswählen

re.findall("(?:\+|-)?\d+", vstring)
Gruß Karo

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. :wink:

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... ;)