基于条件将python字典值转换为元组

基于条件将python字典值转换为元组,python,Python,我试图从下面的dict中得到一个输出,作为下面提到的元组- 输入:b={'a':'1','S1':'OptionA','P1':'100','S2':'','P2':'','S3':'OptionB','P3':'80'} 输出:[('OptionA','100'),('OptionB','80')] 我已经像下面这样编码了,但是我想要一个更短的方法,有人可以建议吗- import re b = {'a':'1','S1':'OptionA','P1':'100','S2':'', 'P2':'

我试图从下面的dict中得到一个输出,作为下面提到的元组-

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

输出:[('OptionA','100'),('OptionB','80')]

我已经像下面这样编码了,但是我想要一个更短的方法,有人可以建议吗-

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)

我只会使用异常处理忽略不符合您模式的键:

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

减少行数并不一定能改进代码。

也许可以使用一行列表

>>> 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')]
只有用于匹配
S
的非空值才与
p
配对


根据评论更新案例。如果需要将
Stgy1
Per1
匹配,列表理解解决方案将开始失去魅力,变得有点不可读。如果您不能简化配对条件,那么for循环可能是一种更干净的方法

>>> 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')]

你的解决方案有效吗?如果是,您所说的
较短的方法是什么意思?更快?线少了。。。??你为什么不喜欢你的解决方案?这个解决方案很有效,我只想要少一些线更多的线。。。但绝对更容易阅读,没有正则表达式和嵌套循环。。。我认为,原始代码不会对不以数字结尾的键进行配对,如
Sx
Px
@randomir Touché:)已修复。如果存在一个键
而没有相应的
P7
,则可以添加一个元组,如
('foo',None)
。原始代码避免了这一点。我不确定OP是否需要这样做,但你是对的。我已经修好了,谢谢。为了更接近原始代码,我还添加了对键中数字的测试。这几乎是我正在寻找的,但当我的输入如下>>b={'a':'1','Stgy1':'OptionA','Per1':'100','Stgy2':'','Per2':'','Stgy3':'OptionB','Per3':'80'}无论如何,我已经根据我的要求对其进行了修改。谢谢,我也更新了答案来处理这个案子。它仍然更短,但不再那么可读了。