使用If Else的Python嵌套列表理解

时间:2014-02-18 10:14:19

标签: python list-comprehension

我试图使用列表推导来替换值列表中的多个可能的字符串值。

我有一个列名列表,这些列名取自cursor.description;

['UNIX_Time', 'col1_MCA', 'col2_MCA', 'col3_MCA', 'col1_MCB', 'col2_MCB', 'col3_MCB']

然后我header_replace;

{'MCB': 'SourceA', 'MCA': 'SourceB'}

我想将列名称中找到的header_replace.keys()的字符串值替换为值。

我不得不使用以下循环;

headers = []
for header in cursor.description:
    replaced = False
    for key in header_replace.keys():
        if key in header[0]:
            headers.append(str.replace(header[0], key, header_replace[key]))
            replaced = True
            break

    if not replaced:
        headers.append(header[0])

这给了我正确的输出;

['UNIX_Time', 'col1_SourceA', 'col2_SourceA', 'col3_SourceA', 'col1_SourceB', 'col2_SourceB', 'col3_SourceB']

我尝试使用此列表理解;

[str.replace(i[0],k,header_replace[k]) if k in i[0] else i[0] for k in header_replace.keys() for i in cursor.description]

但这意味着对于不匹配的密钥,项目是重复的,我会得到;

['UNIX_Time', 'col1_MCA', 'col2_MCA', 'col3_MCA', 'col1_SourceA', 'col2_SourceA', 'col3_SourceA', 
'UNIX_Time', 'col1_SourceB', 'col2_SourceB', 'col3_SourceB', 'col1_MCB', 'col2_MCB', 'col3_MCB']

但如果相反我使用;

[str.replace(i[0],k,header_replace[k]) for k in header_replace.keys() for i in cursor.description if k in i[0]]

@Bakuriu修复语法

我会得到正确的替换品,但随后松开任何不需要替换字符串的物品。

['col1_SourceA', 'col2_SourceA', 'col3_SourceA', 'col1_SourceB', 'col2_SourceB', 'col3_SourceB']

是否有这样做的pythonesque方式或我是否超过了列表推导?我当然觉得它们难以阅读。

3 个答案:

答案 0 :(得分:4)

[str.replace(i[0],k,header_replace[k]) if k in i[0] for k in header_replace.keys() for i in cursor.description]

这是SyntaxError,因为if表达式必须包含else部分。你可能意味着:

[i[0].replace(k, header_replace[k]) for k in header_replace for i in cursor.description if k in i[0]]

最后if。但是我必须说嵌套循环的列表理解通常不是可行的方法。 我会使用扩展的for循环。实际上我会改进它删除replaced标志:

headers = []
for header in cursor.description:
    for key, repl in header_replace.items():
        if key in header[0]:
            headers.append(header[0].replace(key, repl))
            break
    else:
        headers.append(header[0])

在迭代期间没有触发else时,执行for循环的break


我不明白为什么在您的代码中使用str.replace(string, substring, replacement)代替string.replace(substring, replacement)。字符串有实例方法,所以你就这样,而不是它们是类的静态方法。

答案 1 :(得分:1)

如果您的数据与您描述的完全一致,则不需要嵌套替换,并且可以将其归结为此行:

l = ['UNIX_Time', 'col1_MCA', 'col2_MCA', 'col3_MCA', 'col1_MCB', 'col2_MCB', 'col3_MCB']
[i.replace('_MC', '_Source')  for i in l]

>>> ['UNIX_Time',
>>>  'col1_SourceA',
>>>  'col2_SourceA',
>>>  'col3_SourceA',
>>>  'col1_SourceB',
>>>  'col2_SourceB',
>>>  'col3_SourceB']

答案 2 :(得分:0)

我想一个函数会更具可读性:

def repl(key):
    for k, v in header_replace.items():
        if k in key:
            return key.replace(k, v)
    return key

print map(repl, names)

另一个(不太可读)选项:

import re
rx = '|'.join(header_replace)
print [re.sub(rx, lambda m: header_replace[m.group(0)], name) for name in names]