2016-03-25 12 views
3

Ich bin ein Anfänger zu Python regexes. Ich habe erreicht, was ich brauchte, aber es ist wirklich hässlich, da mir die Erfahrung fehlt. Mein Ziel ist es, ein Array von Zeichenfolgen der Form zu konvertieren:Python Regex String-Array zu Float-Array

notes = ["10.0% higher", "5.0% lower", "Same as", "21.2% lower"] 

zu einer Reihe von Schwimmern, so dass die oben genannten Array ergibt:

changes = [10.0,-5.0,0,-21.2] 

Der folgende Code wird erreicht, dass aber wirklich wiederholend und schlechter Stil. Wie kann ich das optimieren?

changes = [] 
for note in notes: 
    m = re.search(r"(?:(\d+\.\d+\%\shigher)|(\d+\.\d+\%\slower)|(Same\sas))", note) 
    if m: 
     if m.groups(0): 
      if m.groups(0)[0]: 
       changes += [float(re.match(r"(\d+\.\d+)", m.groups(0)[0]).groups(0)[0])] 
      elif m.groups(0)[1]: 
       changes += [-float(re.match(r"(\d+\.\d+)", m.groups(0)[1]).groups(0)[0])] 
      else: 
       changes += [0.0] 
print changes 
+1

Sie sollten dies wirklich auf CodeReview.SE schreiben ... Sie könnten diese 2 if-Anweisungen auch ändern, wenn m: if m.groups (0): ', auf eins, wenn m und m.groups (0): ' – Druzion

Antwort

1

Mit findall können Sie d o dies in einem einzigen Regex:

notes = ["10.0% higher", "5.0% lower", "Same as", "21.2% lower"] 

changes = [] 
for note in notes: 
    m = re.findall("(?:(\d+\.\d+)%)?(higher|lower|Same as)", note) 
    if len(m): 
     if m[0][1] == 'higher': 
      changes += [float(m[0][0])] 
     elif m[0][1] == 'lower': 
      changes += [-float(m[0][0])] 
     else: 
      changes += [0.0] 

print changes 
+1

das ist die verständlichste Lösung für mich – niklas

1
import re 

def get_val(s): 
    if "higher" in s: 
     return float(re.sub("\D", "", s)) 
    if "lower" in s: 
     return -float(re.sub("\D", "", s)) 
    return 0 

notes = ["10.0% higher", "5.0% lower", "Same as", "21.2% lower"]  
changes = [get_val(s) for s in notes] 
print(changes) 

druckt

[100.0, -50.0, 0, -212.0] 

viel schneller als regex (relevant für große Eingänge, für kleinere Eingänge nicht so viel) würde string.translate sein:

import string 

all_chars = string.maketrans('', '') 
no_digits = all_chars.translate(all_chars, string.digits) 

def get_val(s): 
    if "higher" in s: 
     return float(s.translate(all_chars, no_digits)) 
    if "lower" in s: 
     return -float(s.translate(all_chars, no_digits)) 
    return 0 

notes = ["10.0% higher", "5.0% lower", "Same as", "21.2% lower"] 
changes = [get_val(s) for s in notes] 
print(changes) 
1
  • Sie können sie variabel und visuell Split-Gruppen
  • Sie können Schwimmer Strings in dieses Muster und konvertieren setzen Muster direkt
  • Sie or abgestimmt auswählen können
  • Gruppe

Beispiel:

import re 


notes = ["10.0% higher", "5.0% lower", "Same as", "21.2% lower"] 

pattern = '(?:' \ 
    '((\d+\.\d+)\%\shigher)|' \ 
    '((\d+\.\d+)\%\slower)|' \ 
    '(Same\sas)' \ 
')' 

changes = [] 

for note in notes: 
    gr = re.search(pattern, note).groups() 
    num = float(gr[1] or gr[3] or 0) * (-1 if gr[3] else 1) 
    changes.append(num) 

print(changes) # [10.0, -5.0, 0.0, -21.2] 
0
#! python3 

notes = ["10.0% higher", "5.0% lower", "Same as", "21.2% lower"] 

def adjustments(notes): 
    for n in notes: 
     direction = -1.0 if n.endswith('lower') else 1.0 
     offset = 0.0 if n.lower() == 'same as' else float(n.split('%')[0]) 
     yield offset * direction 

changes = [x for x in adjustments(notes)] 
print(changes)