Как проверить индивидуальный вывод в понимании списка не является нулевым без повторного вычисления объекта - PullRequest
0 голосов
/ 02 марта 2020

Я пытаюсь использовать понимание списка, чтобы удалить некоторые символы из списка строк. Следовательно, я использую регулярное выражение для их удаления, но вывод регулярного выражения может быть пустым. Можно ли как-нибудь удалить эти выходные данные, не добавляя лишний l oop в массив или не запуская регулярное выражение?

Допустим, у меня есть следующий массив:

>>> example
["a ", "    ", "", "a. &//*-_", " n", "   b   ", "*"]

Вывод, который я хочу получить:

>>> func(example)
'a#a &//_#n#b'

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

def func(example):
    pattern = "[^\w\s\&\/]"
    return "#".join(re.sub(pattern, "", unidecode(tag).lower().strip()) for tag in example)

>>> func(example)
'a###a &//_#n#b#'

Одна возможность, о которой я подумал, заключается в следующем, но мне было интересно, если это снова вычисляет всю обработку строки:

def func2(example):
    pattern = "[^\w\s\&\/]" # The pattern here is not particularly important, I just want to remove some weird characters and keep a couple
    return "#".join(re.sub(pattern, "", unidecode(tag).lower().strip()) for tag in example if re.sub(pattern, "", unidecode(tag).lower().strip()))

>>> func2(example)
'a#a &//_#n#b'

1 Ответ

1 голос
/ 07 марта 2020

Этот общий метод работает:

  1. создайте генератор, дающий элементы, которые вычисляются дважды или более;
  2. используйте этот генератор в понимании списка.

В вашем случае:

>>> import re
>>> from unidecode import unidecode
>>> example = ["a ", "    ", "", "a. &//*-_", " n", "   b   ", "*"]
>>> def func3(example):
...     pattern = "[^\w\s\&\/]"
...     return "#".join(x for x in (re.sub(pattern, "", unidecode(tag).lower().strip()) for tag in example) if x)
>>> func3(example)
'a#a &//_#n#b'

(re.sub(pattern, "", unidecode(tag).lower().strip()) for tag in example) - это генератор, а затем вы фильтруете этот генератор по значениям, которые оцениваются как True.


Примечание: вы в вашем конкретном случае c можно также использовать встроенный filter:

>>> def func4(example):
...     pattern = "[^\w\s\&\/]"
...     return "#".join(filter(None, (re.sub(pattern, "", unidecode(tag).lower().strip()) for tag in example)))
>>> func4(example)
'a#a &//_#n#b'

С do c:

filter(function, iterable) [...] Если для функции задано None, предполагается, что тождественная функция, то есть , все элементы итерируемого, которые являются ложными, удаляются . (выделение мое)

...