Reputation: 3
I am trying to get an output from below dict as a tuple mentioned below-
Input: b = {'a':'1','S1':'OptionA','P1':'100','S2':'', 'P2':'','S3':'OptionB','P3':'80'}
Output : [('OptionA', '100'), ('OptionB', '80')]
i have coded for this like below but i want a shorter method , can anyone please suggest -
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)
Upvotes: 0
Views: 140
Reputation: 18697
Maybe with a list comprehension 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')]
Only non-empty values for matching S<digits>
are paired with P<digits>
.
Update for the case from comments. If you need to match Stgy1
with Per1
, the list comprehension solution starts to lose its charm and becomes a bit unreadable. If you can't simplify your pairing criteria, the for
loop is probably a cleaner way to go.
>>> 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')]
Upvotes: 0
Reputation: 531808
I would just use exception handling to ignore keys that don't fit your pattern:
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))
Having fewer lines doesn't necessarily improve your code.
Upvotes: 1