2015-10-19 2 views
0

Я пытаюсь преобразовать этот рабочий вложенный forloop в однопользовательское понимание списка & Я не могу заставить его работать. Псевдокод выглядит следующим образом:Python вложенное представление списка профайлов

result = [] 
for x in something: 
    for y in x.address: 
     m = re.search("some pattern to match",y) 
     if m: 
     result += [m.group(1)] 

Любые указатели на то, как я могу это сделать?

+0

Итак, где понимается список? И как это не работает? в чем проблема? – Kasramvd

+1

является 'if', который должен находиться внутри блока' for' или нет? – Kevin

+0

Предполагается, что он находится внутри блока. Извините за опечатку. – hmmm

ответ

1

Вам понадобится выражение генератор ..

matches = (re.search(r'some pattern to match', y) for x in something 
                for y in x.address ) 
result = [ m.group(1) for m in matches if m ] 
+0

спасибо за ответ. Просто любопытно - почему здесь требуется выражение генератора? Предполагая, что у меня нет оператора сопоставления шаблонов, я мог бы заставить его работать в одной строке. – hmmm

+0

Поскольку вы не можете сохранить результат re.search в переменную как часть синтаксиса понимания списка. –

+0

Спасибо, это работает. Раньше у меня не было случая использовать генераторы где угодно. Тогда я буду больше читать об этом. Благодаря ! – hmmm

0

Я хотел бы сделать что-то вроде этого:

# match function 
def match(x): 
    m = re.search("some pattern to match",x) 
    if m: 
     return m.group(1) 
    else: 
     return None 

#list comprehension  
results = [match(y) for x in something for y in x.address if match(y)]  
+2

Выполняет 'match()' для каждого элемента * дважды *. – poke

+0

да. не хорошо для длинного списка, но кратким. – zach

1

Вложенные циклы не проблема для списковых, как вы можете вложить те там тоже:

lst = [] 
for y in z: 
    for x in y: 
     lst.append(f(x)) 

Это выражается в следующем списке понимание:

[f(x) for y in z for x in y] 

И вы можете легко продолжить это для нескольких уровней.

условия, которые принимают решение о хотите ли вы что-то добавить в список или нет, также работают просто отлично:

lst = [] 
for x in y: 
    if t(x): 
     lst.append(f(x)) 

Это переводится в следующий список понимания с фильтром:

[f(x) for x in y if t(x)] 

Из Конечно, вы также можете комбинировать это с несколькими уровнями.


что теперь является какой-то проблемы, хотя, когда вы хотите, чтобы выполнить что-то первый, а затем отфильтровать результат, что и добавить также то, что зависит от результата. Наивный решением было бы переместить вызов функции внутри и сделать это дважды:

rexpr = re.compile('some pattern to match') 
[rexpr.search(y).group(1) for x in something for y in x.address if rexpr.search(y)] 

Но это, очевидно, работает поиск в два раза, которые вы обычно хотите избежать. На данный момент вы можете использовать некоторые хакерские решения, которые я обычно не рекомендую (поскольку они ухудшают читаемость). Поскольку ваш результат зависит только от результата поиска регулярных выражений, вы также можете решить это в два этапа: во-первых, вы выполняете поиск по каждому элементу и сопоставляете их с объектом-совпадением, а затем фильтруете по этим совпадениям и просто возвращаете действительный из них:

[m.group(1) for m in (rexpr.search(y) for x in something for y in x.address) if m] 

Обратите внимание, что я использую выражение генератора здесь: это в основном так же, как списковые, но не создают полный результата в виде списка, но выход только на элементе в то время. Таким образом, это более эффективно, если вы только хотите потреблять это по одному (что и есть здесь). В конце концов, вас интересует только результат из понимания списка, поэтому понимание будет потреблять выражение генератора.

+0

спасибо за подробное объяснение. Кажется, что я действительно нуждался здесь, это генераторы и спасибо за варианты использования. – hmmm

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