Python 筛选列表
我想过滤列表中重复的元素 比如说Python 筛选列表,python,list,unique,Python,List,Unique,我想过滤列表中重复的元素 比如说 foo = ['a','b','c','a','b','d','a','d'] 我只对以下方面感兴趣: ['a','b','c','d'] 实现这一目标的有效方法是什么? 干杯如果您不关心元素顺序,请将foo转换为a 列表((foo))如果您使用的是Python 2.5或更高版本,但这并不能维持秩序。如果您关心秩序,可读的方式如下 def filter_unique(a_list): characters = set() result = [
foo = ['a','b','c','a','b','d','a','d']
我只对以下方面感兴趣:
['a','b','c','d']
实现这一目标的有效方法是什么?
干杯如果您不关心元素顺序,请将foo转换为a
列表(
(foo))
如果您使用的是Python 2.5或更高版本,但这并不能维持秩序。如果您关心秩序,可读的方式如下
def filter_unique(a_list):
characters = set()
result = []
for c in a_list:
if not c in characters:
characters.add(c)
result.append(c)
return result
根据您对速度、可维护性和空间消耗的要求,您可能会发现上述方法不适用。在这种情况下,请指定您的要求,我们可以尝试做得更好:-)
这将是从列表中删除重复项并尽可能保留顺序的最直接的方法(即使这里的“顺序”本质上是错误的概念)。如果您编写一个函数来实现这一点,我将使用生成器,它只想在这种情况下使用 def unique(iterable): yielded = set() for item in iterable: if item not in yielded: yield item yielded.add(item) def唯一(iterable): 屈服=集() 对于iterable中的项目: 如果项目不在列表中: 收益项目 添加(项目)
由于没有列表理解的保序答案,我建议如下:
>>> temp = set()
>>> [c for c in foo if c not in temp and (temp.add(c) or True)]
['a', 'b', 'c', 'd']
也可以写成
>>> temp = set()
>>> filter(lambda c: c not in temp and (temp.add(c) or True), foo)
['a', 'b', 'c', 'd']
根据foo
中的元素数量,您可以通过重复的哈希查找而不是通过临时列表进行重复的迭代搜索来获得更快的结果
c不在temp
中验证temp
是否没有项目c
;当项目添加到集合中时,或True
部分强制将c
发送到输出列表中。受此启发,与其制作我们自己的过滤器()
类型函数,不如让内置函数为我们做一些工作:
def unique(a, s=set()):
if a not in s:
s.add(a)
return True
return False
用法:
uniq = filter(unique, orig)
这可能比在纯Python中实现所有工作的答案执行得更快或更慢,也可能不会。基准测试并查看。当然,这只起作用一次,但它展示了这个概念。当然,理想的解决方案是使用类:
class Unique(set):
def __call__(self, a):
if a not in self:
self.add(a)
return True
return False
现在我们可以随心所欲地使用它:
uniq = filter(Unique(), orig)
再一次,我们可能(也可能不是)将性能抛到了窗外——使用内置函数的收益可能会被类的开销抵消。我只是觉得这是一个有趣的想法。如果您需要在末尾列出一个排序列表,这就是您想要的:
>>> foo = ['a','b','c','a','b','d','a','d']
>>> bar = sorted(set(foo))
>>> bar
['a', 'b', 'c', 'd']
你可以做一个丑陋的列表理解黑客
[l[i] for i in range(len(l)) if l.index(l[i]) == i]
sri以2秒的优势击败了你:p@Helinar:那不是真的,fatcat1111比我快1秒是的,我认为fatcat1111比我快1秒,所以如果你和我一样有帮助的话,你应该接受上面的答案:-)@sri-你的答案提供了更多信息-它显示了一个代码示例(无论多么简短),并提到了2.5+的要求。没有“cast”。也许你的意思是“强制”。至少应该提到O(n^2)的性能特征,不是吗?@silenghost-那里有什么
k
?它是一个常数(即不是大O符号的一部分)还是其他因素?我不认为它是O(n^2)。它可能是O(不是很好),但也没那么糟。@Chris-我相信Triptych和hughdbrown指出了bar上的追加操作可能不是固定时间(快速但无动力的docs.python.org检查没有发现太多).我认为SilentGhost的意思是常数。没关系。在我读函数的前七次左右的时候,我完全错过了if语句中的成员资格测试。是的,O(n^2)。为什么要将已在None
s散列中找到的项目存储在集合中而不是集合中呢?因为我一直都不这么认为。+1您的答案启发我创建了一个类,允许使用内置的过滤器()< /代码>做同样的事情。所以谢谢你的灵感。“克里斯:我的荣幸:-”我认为使用过滤器会稍微更先进,所以去一个非常简单的解决方案。如果你喜欢过滤器考虑使用(优秀)模块itertools,特别是itertools.ifilter和itertools.ifilterfalselist理解是多余的。可以说:bar=sorted(set(foo))回答得好——直接回答问题(尽管不完全诚实)它的输出是自然排序的。+1。@pst:不完全是诚实的?好像我想对你做点什么?或者……什么?我不明白OP要求的是稳定排序,所以我只是对它们进行排序,因为这看起来是一个要求。@recursive:很好的调用。我会编辑它。如果运行两次会发生什么?uniq=filter(Unique(),range(10));print uniq
实际上,我的意思是如果你运行两次:uniq=filter(unique,range(10));print uniq
unique版本只工作一次。在相同的数据上再次运行它将不会产生任何数据,因为函数只有一个集合(第二个参数)。在不同的数据上运行两次可能会产生意外的结果,因为它将消除两个数据集的重叠以及第二个数据集的重复。该函数是我的第一个版本,它的局限性使我创建了类版本,该类版本不会遇到此类问题(而且通常也更有用).函数版本只是一个思维过程,仅此而已。
import numpy as np
np.unique(foo)
[l[i] for i in range(len(l)) if l.index(l[i]) == i]