我有一个小代码,它需要一个对象列表,并且只输出列表中唯一的项目。
这是我的代码
def only_once(a):
return [x for x in a if a.count(x) is 1]
不过,我的老师要求我们为此功能使用集合。有人可以告诉我我能做什么吗?
我的代码必须接受 a=[1,4,6,7,3,2,4,5,7,5,6] 之类的输入,然后输出 [1, 3, 2]。也必须保持它的顺序。
我有一个小代码,它需要一个对象列表,并且只输出列表中唯一的项目。
这是我的代码
def only_once(a):
return [x for x in a if a.count(x) is 1]
不过,我的老师要求我们为此功能使用集合。有人可以告诉我我能做什么吗?
我的代码必须接受 a=[1,4,6,7,3,2,4,5,7,5,6] 之类的输入,然后输出 [1, 3, 2]。也必须保持它的顺序。
澄清一下,您想要的是一组出现一次且仅出现一次的项目。
这里最好的选择是使用collections.Counter()
,因为这意味着您只计算项目一次,而不是每个项目一次,从而大大提高性能:
>>> import collections
>>> {key for key, count in collections.Counter(a).items() if count == 1}
{1, 2, 3}
我们只需用花括号替换方括号,以表示集合推导优于列表推导,从而获得一组结果。
如果您需要多次删除列表中的任何项目,而不仅仅是第一个之后的出现,您可以使用:
# without using generators / comprehensions
def only_once(iterable):
seen = set()
duplicates = set()
for item in iterable:
if item in seen:
duplicates.add(item)
seen.add(item)
result = []
for item in iterable:
if item not in duplicates:
result.append(item)
return result
对于一般的订单保留重复消除,请参阅unique_everseen
itertools recipes:
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
[我假设您也是 user1744238 和 user1744316 - 请选择一个用户名并坚持使用它,这样更容易检查您提出的问题的变体以及您已经尝试过的问题。]
一种基于集合的方法是使用两个集合作为计数器。你只关心你是否见过一次或不止一次。例如,这是一个易于解释的方法:
once
为和做一个空集more
。once
.once
并添加到more
.once
。once
集合中删除,这样您就不会两次输出相同的元素。这给了我:
In [49]: f([1,4,6,7,3,2,4,5,7,5,6])
Out[49]: [1, 3, 2]