2014-02-18 4 views
1

Я пытался использовать понимание списка, чтобы заменить несколько возможных строковых значений в списке значений.Python Вложенное представление списка с If Eles

У меня есть список имен столбцов, которые взяты из 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'] 

Есть ли питонесский способ сделать это, или я над разборчивыми списками? Я, конечно, их трудно читать.

+0

Что вы имеете в виду 'output'? Содержимое 'заголовков'? – Bach

+4

Я придерживаюсь циклов и избегаю списков. Мое эмпирическое правило состоит в том, что, если вы делаете больше, чем одно в понимании, его, вероятно, лучше всего расширять в цикл с помощью .append. – sneeu

+0

'cursor.description' содержит список строк. 'header [0]' содержит один символ. Это специально? – Bach

ответ

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). Строки имеют экземпляры методов, поэтому вы их как таковые, а не как статические методы класса.

+0

Спасибо, не знали о' else' в 'for' который может быть действительно полезен. Какова цель '_'? –

+0

@DaveAnderson Я использую распаковку кортежей, чтобы избежать использования 'header [0]' все время. Но я просто изменил его, потому что это сработает, только если 'cursor.description' является парой, но поскольку он может иметь любое количество элементов, я решил отбросить это назад. Символ '_' не имеет особого значения. Это часто используется для обозначения «переменной, которую я не буду использовать, но это необходимо». Это соглашение, вероятно, было взято из Haskell, где * * - специальный шаблон, который означает «любое значение соответствует». – Bakuriu

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] 
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'] 
+0

К сожалению, обычные 'MC' и' Source' не гарантированы, что это может быть что угодно: от «M00» до «MFF», а значения замены могут быть почти любыми. –

+0

В этом случае я бы посоветовал написать специализированную функцию замены строки M_replace (source_string) – aisbaa

+0

В этом случае я бы пошел с регулярными выражениями вместо огромного словаря замещений. – Michael

Смежные вопросы