2017-07-22 1 views
0

Ich versuche, eine Ausgabe von unten dict als Tupel unten-Python Wörterbuch Werte in Tupel basierend auf Zustand

Eingang erwähnt zu erhalten: b = { 'a': '1', 'S1': 'OptionA', 'P1': '100', 'S2': '', 'P2': '', 'S3': 'OptionB', 'P3': '80'}

Ausgabe: [('optiona', '100'), ('OptionB', '80')]

ich habe für diese codiert wie unten, aber ich mag ein kürzeres Verfahren, kann dich jemand bitte vorschlagen -

import re 
b = {'a':'1','S1':'OptionA','P1':'100','S2':'', 'P2':'','S3':'OptionB','P3':'80'} 

c =[] 
for k,v in b.items(): 
    if k.startswith('S') and v: 
     for i,j in b.items(): 
      if i.startswith('P') and re.search(r'\d+$', k).group() == re.search(r'\d+$', i).group(): 
       c.append(tuple([v,j])) 

print(c) 
+0

Funktioniert Ihre Lösung? Wenn ja, was meinst du mit einer "kürzeren Methode"? schneller? weniger Linien? ... ?? Warum magst du deine Lösung nicht? – wwii

+0

Die Lösung funktioniert, ich will nur weniger Zeilen – LalitK

Antwort

0

Vielleicht mit einem Listenverständnis oneliner?

>>> b = {'a':'1','S1':'OptionA','P1':'100','S2':'', 'P2':'','S3':'OptionB','P3':'80'} 
>>> [(v, b['P'+k[1:]]) for k,v in b.items() if re.match('^S\d+$',k) and v and 'P'+k[1:] in b] 
[('OptionB', '80'), ('OptionA', '100')] 

Nur nicht leere Werte für den Abgleich S<digits> mit P<digits> gepaart.


aktualisieren für den Fall von Kommentaren. Wenn Sie Stgy1 mit Per1 übereinstimmen müssen, verliert die List Comprehension-Lösung ihren Charme und wird ein wenig unlesbar. Wenn Sie Ihre Paarungskriterien nicht vereinfachen können, ist der for Loop wahrscheinlich ein saubererer Weg.

>>> b = {'a':'1','Stgy1':'OptionA','Per1':'100','Stgy2':'', 'Per2':'','Stgy3':'OptionB','Per3':'80'} 
>>> [(v, w) for s,v in b.items() for p,w in b.items() if s[0]=='S' and p[0]=='P' and v and w and re.search('\d+$',s).group()==re.search('\d+$',p).group()] 
[('OptionB', '80'), ('OptionA', '100')] 
+0

Dies kann ein Tupel wie '('foo', None) hinzufügen, wenn beispielsweise eine Taste' S7' ohne ein entsprechendes 'P7' vorhanden ist. Der ursprüngliche Code vermeidet dies. – chepner

+0

Ich bin mir nicht sicher, ob das die OP verlangt, aber du hast Recht. Ich habe es behoben, danke. Um noch näher am ursprünglichen Code zu sein, fügte ich auch einen Test für Ziffern in Schlüsseln hinzu. – randomir

+0

das ist fast das, was ich suche, aber es bricht, wenn meine Eingabe wie folgt ist >>> b = {'a': '1', 'Stgy1': 'OptionA', 'Per1': '100', 'Stgy2 ':' ',' Per2 ':' ',' Stgy3 ':' OptionB ',' Per3 ':' 80 '} – LalitK

1

Ich würde nur Exception Handling Schlüssel zu ignorieren, die passen Ihr Muster nicht:

c = [] 
for k, v in b.items(): 
    if not k.startswith('S') or not v: 
     continue 
    new_key = v 
    try: 
     n = int(k[1:]) 
     new_value = b['P%d' % (n,)] 
    except KeyError, ValueError: 
     continue 
    c.append((new_key, new_value)) 

weniger Leitungen nicht unbedingt Ihren Code verbessern.

+0

Mehr * Zeilen * ... aber auf jeden Fall einfacher zu lesen und keine regulären Ausdrücke und keine verschachtelten Schleifen ... [KISS] (https://en.wikipedia.org/wiki/ KISS_principle) – wwii

+0

Der ursprüngliche Code paßt keine Schlüssel, die nicht mit Ziffern enden, wie 'Sx' und' Px'. – randomir

+1

@randomir Touché :) Fest, denke ich. – chepner

Verwandte Themen