我想生成一个生成器函数,该函数遍历输入可迭代序列,一次生成一个元素,但跳过重复项。下面是一个示例代码:
numbers = [4, 5, 2, 6, 2, 3, 5, 8]
nums = unique(numbers)
next(nums)
4
next(nums)
5
next(nums)
2
next(nums)
6
next(nums)
3
next(nums)
8
有人知道为什么不打印此代码吗?
def unique(iterable):
seen = set()
for n in iterable:
if n not in seen:
seen.add(n)
yield n
numbers = [4, 5, 2, 6, 2, 3, 5, 8]
nums = unique(numbers)
print(next(nums))
答案 0 :(得分:4)
一个简单的唯一生成器将只保留set
个已经看到的项目,例如:
def unique(nums):
seen = set()
for n in nums:
if n not in seen:
seen.add(n)
yield n
In []:
numbers = [4, 5, 2, 6, 2, 3, 5, 8]
list(unique(numbers))
Out[]:
[4, 5, 2, 6, 3, 8]
答案 1 :(得分:3)
最简单的方法是use OrderedDict
,这是一种在保留订单的同时进行重复数据删除的简单方法:
from collections import OrderedDict
def unique(nums):
yield from OrderedDict.fromkeys(nums)
从技术上讲,它急切地运行(所有重复数据删除都在前面完成,然后迭代完全重复数据删除的OrderedDict
),但是所有其他解决方案最终都需要构建等效的set
,因此这会延迟第一个值的产生,但总体上却要完成相同的工作量(并且在使用C实现的OrderedDict
的Python版本上,运行速度比使用set
作为“可见”的生成器的手动滚动更快。商店)。它不适合的情况是无限输入可迭代项和有限但较大的可迭代项,在这些情况下,您很可能在完成之前会停止处理它们(在这种情况下,基于{{1}的惰性unique_everseen
解决方案})。
在Python 3.6及更高版本上,plain dict
preserves order(尽管it's not an official guarantee until 3.7),因此您甚至不需要导入:
set
答案 2 :(得分:0)
您是否需要发电机?为什么不只使用set
?
numbers = [4, 5, 2, 6, 2, 3, 5, 8]
for i in set(numbers):
print(i)
如果您确实需要发电机:
def skipper(l):
for i in set(l):
yield i
for i in skipper(numbers):
print(i)