Как удалить соседние повторяющиеся элементы в списке с помощью list comprehensions? [дубликат]
этот вопрос уже есть ответ здесь:
есть ли способ использовать понимание списка в python для фильтрации примыкает дубликаты из списка?
вот пример что я имею в виду:
>>> xs = [1,2,2,3]
>>> print added.reAdj(xs)
[1,2,3]
поиск через SE показал более ранний запрос спрашивать как но немного другой вопрос: Можно ли удалить все дубликаты из списка, но не явно запрашивать решения, связанные с пониманием списка. Мотивация для использования списка постижений специально следует за признанием их преимущества перед традиционными для петель. Пользователи предложили использовать функцию set () или стандартный цикл как такие:
result = []
most_recent_elem = None
for e in xs:
if e != most_recent_elem:
result.append(e)
most_recent_elem = e
на set()
предложение не отвечает задаче в том, что не смежные дубликаты удаляются, в то время как цикл эффективен, но многословен.
кажется, что необходимо безопасно ссылаться на следующий элемент в понимании списка следующим образом.
[x for x in xs if x != **x.next()**]
какие идеи?
5 ответов
вы могли бы использовать list comprehension
и enumerate
С решением, предложенным @AChampion:
xs = [1,2,2,2,1,1]
In [115]: [n for i, n in enumerate(xs) if i==0 or n != xs[i-1]]
Out[115]: [1, 2, 1]
этот элемент возврата понимания списка, если он первый или следующий, если он не равен предыдущему. Это будет работать из-за ленивых оценок if
заявление.
можно использовать itertools.groupby
:
>>> import itertools
>>> [key for key, grp in itertools.groupby([1, 2, 2, 3])]
[1, 2, 3]
itertools.groupby
возвращает итератор. Повторяя его, вы получите ключ, групповые пары. (key
будет пункт, если нет key
функция указана, в противном случае возвращается значение
использование попарно из рецептов itertools (с zip_longest) дает вам простой способ проверить следующий элемент:
import itertools as it
def pairwise(iterable):
a, b = it.tee(iterable)
next(b, None)
return it.zip_longest(a, b, fillvalue=object()) # izip_longest for Py2
>>> xs = [1,2,2,3]
>>> [x for x, y in pairwise(xs) if x != y]
[1, 2, 3]
>>> xs = [1,2,2,2,2,3,3,3,4,5,6,6]
>>> [x for x, y in pairwise(xs) if x != y]
[1, 2, 3, 4, 5, 6]
вы можете использовать менее подробное решение цикла:
>>> result = xs[:1]
>>> for e in xs:
if e != result[-1]:
result.append(e)
или:
>>> result = []
>>> for e in xs:
if e not in result[-1:]:
result.append(e)
как насчет этого:
>>> l = [1,1,2,3,4,4,4,4,5,6,3,3,5,5,7,8,8,8,9,1,2,3,3,3,10,10]
>>>
>>> o = []
>>> p = None
>>> for n in l:
if n == p:
continue
o.append(n)
p = n
>>> o
[1, 2, 3, 4, 5, 6, 3, 5, 7, 8, 9, 1, 2, 3, 10]
по-видимому, выше решение более многословно, чем OP, так что вот альтернатива этому, используя zip_longest
С itertools
модуль:
>>> l
[1, 1, 2, 3, 4, 4, 4, 4, 5, 6, 3, 3, 5, 5, 7, 8, 8, 8, 9, 1, 2, 3, 3, 3, 10, 10]
>>> from itertools import zip_longest
>>> o = [p for p,n in zip_longest(l,l[1:]) if p != n] #By default fillvalue=None
>>> o
[1, 2, 3, 4, 5, 6, 3, 5, 7, 8, 9, 1, 2, 3, 10]