Python 如何使用列表理解删除列表中相邻的重复元素?
有没有一种方法可以在python中使用列表理解来过滤列表中相邻的重复项 这里有一个例子来说明我的意思:Python 如何使用列表理解删除列表中相邻的重复元素?,python,list,list-comprehension,Python,List,List Comprehension,有没有一种方法可以在python中使用列表理解来过滤列表中相邻的重复项 这里有一个例子来说明我的意思: >>> xs = [1,2,2,3] >>> print added.reAdj(xs) [1,2,3] 通过搜索SE发现一个类似但略有不同的问题:是否可以从列表中删除所有重复项,但没有明确询问涉及列表理解的解决方案。使用列表理解的动机具体地遵循了认知。用户建议使用set()函数或标准循环: result = [] most_recent_elem = N
>>> 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()**]
有什么想法吗?您可以使用:
itertools.groupby
返回迭代器。通过迭代,您将得到一个键,组对。(如果未指定键
函数,则键
将成为一项,否则键
函数的返回值)group
是一个迭代器,它将通过应用key
函数生成分组的项(如果未指定,将分组相同的值)
导入itertools
>>>it=itertools.groupby([1,2,2,3])
>>>它
>>>对于键,请在其中输入:
... 打印(键)
... 印刷品(玻璃钢)
...
1.
2.
3.
>>>it=itertools.groupby([1,2,2,3])
>>>对于键,请在其中输入:
... 打印(列表(grp))
...
[1]
[2, 2]
[3]
在上面的解决方案中,我只使用了键
,因为问题并不关心有多少项相邻。您可以使用@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
语句的延迟计算,它将起作用。您可以使用一种不太详细的循环解决方案:
>>> result = xs[:1]
>>> for e in xs:
if e != result[-1]:
result.append(e)
或:
使用itertools菜谱中的两两(zip_最长)可以方便地检查下一个元素:
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]
这个怎么样:
>>> 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的更详细,因此这里有一个替代使用fromitertools
模块的解决方案:
>>> 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]
这是否意味着即使
[1,2,2,2,2,3,3,4,5,6,6]-->[1,2,3,4,5,6]
?@IronFist,您理解正确。“这是期望的结果。”阿坎皮恩说。谢谢你的链接,但据我所知,这张海报并没有特别要求回答涉及列表理解的问题。我最初的问题帖子包含了一个循环解决方案。稍微挑剔:它删除了尾随的None
值。注意:但不是一个int列表问题。并且可以通过向zip\u longest
添加fillvalue
来避免,修复了@安东波波夫。请在取得进展时更新。不幸的是,Stefan Pochmann提出的案例不起作用,因为你的解决方案在其他方面非常优雅。@Antonprotopov-请,请,请将AChampion建议的解决方案纳入你的答案中。这比对itertools
中的某个不可理解函数的不可理解的调用要好得多。@DavidHammengroupby
很简单也很好,你不应该因为自己的不足而责备它。@antopropov-现在你得到了一个负一。众所周知,xs[-1]
是python中数组的最后一个元素。如果你没有纠正这一点,你的答案就大错特错了。似乎错误是显而易见的。在接下来的几个小时里,如果有人提出任何其他问题,我会接受这个答案。这个答案是有效的,但它的逻辑与OP完全相同,只是稍微有点冗长。@AlexanderHuszagh。。是的…我忘了详细更新的那一点。。使用zip_longest
在没有排序输入的情况下使用groupby
是很奇怪的,但我想这在这个特定的用例中是非常合适的
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]
>>> 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]
>>> 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]