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

Как удалить смежные повторяющиеся элементы в списке, используя списки?

Есть ли способ использовать методы списка в 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()**]

Любые идеи?

4b9b3361

Ответ 1

Вы можете использовать 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.

Ответ 2

Вы можете использовать itertools.groupby:

>>> import itertools
>>> [key for key, grp in itertools.groupby([1, 2, 2, 3])]
[1, 2, 3]

itertools.groupby возвращает итератор. Повторяя это, вы получите ключ, группы пар. (key будет элементом, если не указана функция key, в противном случае возвращаемое значение функции key). group - это итератор, который даст элементы, сгруппированные с помощью функции key (если не указано, одинаковые значения будут сгруппированы)

>>> import itertools
>>> it = itertools.groupby([1, 2, 2, 3])
>>> it
<itertools.groupby object at 0x7feec0863048>
>>> for key, grp in it:
...     print(key)
...     print(grp)
... 
1
<itertools._grouper object at 0x7feec0828ac8>
2
<itertools._grouper object at 0x7feec0828b00>
3
<itertools._grouper object at 0x7feec0828ac8>
>>> it = itertools.groupby([1, 2, 2, 3])
>>> for key, grp in it:
...     print(list(grp))
... 
[1]
[2, 2]
[3]

Выше решения я использовал только key, потому что вопрос не волнует, сколько элементов смежно.

Ответ 3

Использование попарно из рецептов 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]

Ответ 4

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

>>> 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)

Ответ 5

Как насчет этого:

>>> 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]