Подтвердить что ты не робот

Как использовать повторно сопоставляемые объекты в понимании списка

У меня есть функция для выделения комков из списка строк и возврата их в виде другого списка:

def filterPick(lines,regex):
    result = []
    for l in lines:
        match = re.search(regex,l)
        if match:
            result += [match.group(1)]
    return result

Есть ли способ переформулировать это как понимание списка? Очевидно, это довольно ясно, как есть; просто любопытно.


Спасибо тем, кто внес свой вклад, специально для @Alex. Здесь конденсированная версия того, с чем я столкнулся; метод совпадения регулярных выражений передается filterPick как "предварительно поднятый" параметр:

import re

def filterPick(list,filter):
    return [ ( l, m.group(1) ) for l in list for m in (filter(l),) if m]

theList = ["foo", "bar", "baz", "qurx", "bother"]
searchRegex = re.compile('(a|r$)').search
x = filterPick(theList,searchRegex)

>> [('bar', 'a'), ('baz', 'a'), ('bother', 'r')]
4b9b3361

Ответ 1

[m.group(1) for l in lines for m in [regex.search(l)] if m]

"трюк" - это часть for m in [regex.search(l)] - то, как вы "назначаете" значение, которое вам нужно использовать более одного раза, в понимании списка - добавьте только такое предложение, где объект "итерации" над списком с одним элементом, содержащим одно значение, которое вы хотите "назначить" ему. Некоторые считают это стилистически сомнительным, но иногда я считаю это практичным.

Ответ 2

return [m.group(1) for m in (re.search(regex, l) for l in lines) if m]

Ответ 3

Его можно немного сократить

def filterPick(lines, regex):
    matches = map(re.compile(regex).match, lines)
    return [m.group(1) for m in matches if m]

Вы можете поместить все в одну строку, но это означало бы, что вам придется сопоставлять каждую строку дважды, что было бы немного менее эффективным.

Ответ 4

Начиная с Python 3.8 и введением выражений присваивания (PEP 572) (:= оператор), можно использовать локальную переменную в пределах понимания списка, чтобы избежать многократного вызова одного и того же выражения:

# items = ["foo", "bar", "baz", "qurx", "bother"]
[(x, match.group(1)) for x in items if (match := re.compile('(a|r$)').search(x))]
# [('bar', 'a'), ('baz', 'a'), ('bother', 'r')]

Это:

  • re.compile('(a|r$)').search(x) оценку re.compile('(a|r$)').search(x) как match переменной (которая является None или объектом Match)
  • Использует это match именованным выражением на месте (None или Match), чтобы отфильтровать несоответствующие элементы
  • И повторно использует match в сопоставленном значении, извлекая первую группу (match.group(1)).

Ответ 5

>>> "a" in "a visit to the dentist" 
True 
>>> "a" not in "a visit to the dentist" 
False

Это также работает с поисковым запросом, который вы просматриваете в списке

`P = 'a', 'b', 'c'

'b' в P` возвращает true