Здесь уместно понимание списка? - PullRequest
5 голосов
/ 04 августа 2011

Я должен добавлять элементы в список, только если текущий повторяющийся элемент еще не находится в списке.

>>> l = [1, 2]
>>> for x in (2, 3, 4):
...     if x not in l:
...             l.append(x)
... 
>>> l
[1, 2, 3, 4]

против

>>> l = [1, 2]
>>> [l.append(i) for i in (2, 3, 4) if i not in l]
[None, None]
>>> l
[1, 2, 3, 4]

Понимание списка дает результат, который я хочу, просто возвращенный список бесполезен. Это хороший пример использования списочных представлений?

Итерация - хорошее решение, но мне интересно, есть ли более идиоматический способ сделать это?

Ответы [ 4 ]

7 голосов
/ 04 августа 2011

Этот алгоритм с пониманием списка или без него не настолько эффективен, насколько это возможно; list.__contains__ - это O (n), поэтому добавление в него элементов другого списка - это O (n 2 ). С другой стороны, set.__contains__ - это O (log n), поэтому лучший способ сделать это - использовать набор для проверки членства и список для сохранения порядка. Таким образом, вы выполняете n операций, которые являются O (log n), всего O (n log n), что намного быстрее, чем O (n 2 ) для разумных значений n (скажем выше , 100 элементов).

>>> l = [1, 2]
>>> seen = set(l)
>>> for x in (2, 3, 4):
...     if x not in seen:
...         seen.add(x)
...         l.append(x)
... 
>>> l
[1, 2, 3, 4]
>>> 
5 голосов
/ 04 августа 2011

Вы можете сделать:

l.extend((i for i in (2,3,4) if i not in l))

Это решение все еще работает, если добавленный список не является уникальным.

3 голосов
/ 04 августа 2011

Могу предложить еще одно решение:

orig = [1,2]
ext = [2,3,4]
orig.extend(filter( lambda x,p=set(orig):not(x in p or p.add(x)),ext ))

Учитывает порядок элементов и работает при повторении элементов.

Кстати, сложность O (n * log (n)).

3 голосов
/ 04 августа 2011

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

Если l становится действительно длинным, вы можете сохранить параллельный набор, чтобы избежать использования in l в длинном списке

...