如何解决有序集Python 2.7
| 我有一个尝试从中删除重复项的列表。我正在使用python 2.7.1,因此我可以简单地使用set()函数。但是,这重新排列了我的列表。对于我的特殊情况,这是不可接受的。 下面是我编写的函数;做到这一点。但是我想知道是否有更好/更快的方法。此外,对此的任何评论将不胜感激。 def ordered_set(list_):
newlist = []
lastitem = None
for item in list_:
if item != lastitem:
newlist.append(item)
lastitem = item
return newlist
上面的函数假定所有项目都不是None,并且项目按顺序排列(即[\'a \',\'a \',\'a \',\'b \',\' b \',\'c \',\'d \'])
上面的函数返回[\'a \',\'a \',\'a \',\'b \',\'b \',\'c \',\'d \']作为[\ 'A B C D\']。
解决方法
使用OrderedDict:
from collections import OrderedDict
l = [\'a\',\'a\',\'b\',\'c\',\'d\']
d = OrderedDict()
for x in l:
d[x] = True
# prints a b c d
for x in d:
print x,print
, 另一个非常快速的set方法:
def remove_duplicates(lst):
dset = set()
# relies on the fact that dset.add() always returns None.
return [item for item in lst
if item not in dset and not dset.add(item)]
, 假设输入序列是无序的,这里是3解(在空间和时间上)。
它会产生一个序列,其中删除了重复项,同时以与输入序列中出现的相对顺序相同的相对顺序保留了唯一项。
>>> def remove_dups_stable(s):
... seen = set()
... for i in s:
... if i not in seen:
... yield i
... seen.add(i)
>>> list(remove_dups_stable([\'q\',\'w\',\'e\',\'r\',\'q\',\'y\',\'u\',\'i\',\'t\',\'p\',\'e\']))
[\'q\',\'p\']
, 我知道这已经被回答了,但是这里是一线(加上导入):
from collections import OrderedDict
def dedupe(_list):
return OrderedDict((item,None) for item in _list).keys()
>>> dedupe([\'q\',\'e\'])
[\'q\',\'p\']
, 我认为这完全可以。您将获得O(n)性能,这是您所希望的最佳结果。
如果列表是无序的,那么您将需要一个帮手set
来包含您已经访问过的物品,但是对于您而言,则没有必要。
, 如果您的列表未排序,那么您的问题就没有意义。
例如[1,2,1]可能变为[1,2]或[2,1]
如果列表很大,则可能需要使用SLICE将结果写回到同一列表中以节省内存:
>>> x=[\'a\',\'d\']
>>> x[:]=[x[i] for i in range(len(x)) if i==0 or x[i]!=x[i-1]]
>>> x
[\'a\',\'d\']
有关内联删除的信息,请参见在迭代时从列表中删除项目或在迭代时从列表中删除项目,而无需在Python中使用额外的内存
您可以使用的一个技巧是,如果您知道x已排序,并且知道x [i] = x [i + j],则无需检查x [i]和x [i + j]之间的任何内容(如果您不需要删除这些j值,则可以将所需的值复制到新列表中)
因此,如果集合中的所有内容都是唯一的,即您无法击败n次运算,即len(set(x))= len(x)
可能存在一种算法,它的n个比较是最坏的情况,但是可以将n / 2个比较作为它的最佳情况(如果您事先知道len(x)/ len( set(x))> 2,因为您已经生成了数据):
最佳算法可能会使用二分法搜索以分而治之的方式为每个最小值i找到最大值j。初始除法的长度可能为len(x)/近似(len(set(x)))。希望可以这样执行,即使len(x)= len(set(x))仍然只使用n个操作。
, 在中描述了unique_everseen解决方案
http://docs.python.org/2/library/itertools.html
def unique_everseen(iterable,key=None):
\"List unique elements,preserving order. Remember all elements ever seen.\"
# unique_everseen(\'AAAABBBCCDAABBB\') --> A B C D
# unique_everseen(\'ABBCcAD\',str.lower) --> A B C D
seen = set()
seen_add = seen.add
if key is None:
for element in ifilterfalse(seen.__contains__,iterable):
seen_add(element)
yield element
else:
for element in iterable:
k = key(element)
if k not in seen:
seen_add(k)
yield element
, 对我来说还不错。如果您真的想使用集合,请执行以下操作:
def ordered_set (_list) :
result = set()
lastitem = None
for item in _list :
if item != lastitem :
result.add(item)
lastitem = item
return sorted(tuple(result))
我不知道您将获得什么性能,应该进行测试;可能由于方法过热而相同!
如果您真的像我一样偏执,请阅读以下内容:
http://wiki.python.org/moin/HowTo/Sorting/
http://wiki.python.org/moin/PythonSpeed/PerformanceTips
只是想起了这个(它包含答案):
http://www.peterbe.com/plog/uniqifiers-benchmark
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。