我遇到了一个问题,我必须从列表这样的
中过滤掉dupesa = [1,1,4,5,6,5]
这是我的代码:
def unique(a):
uni = []
for value in a:
if value[0] not in found:
yield value
found.add(value[0])
print list(unique(a))
但是,当我定义列表a
并尝试unique(a)
时,我会得到此输出:
<generator object unique at 0x0000000002891750>
有人可以告诉我我做错了什么吗?为什么我不能拿到名单?
编辑,新问题.. 我能够打印出已过滤的列表,但我丢失了列表的顺序。 我该如何防止这种情况?
def unique(a):
s = set()
for i in a:
if i not in s:
s.add(i)
return s
答案 0 :(得分:3)
您必须跟踪已经看到的所有元素。最好的方法是使用set
,因为它的查找复杂度为O(1)
。
>>> def unique(it):
s = set()
for el in it:
if el not in s:
s.add(el)
yield el
>>> list(unique(a))
[1, 4, 5, 6]
如果您不需要保持元素的顺序,则可以使用set
构造函数,然后将其转换回列表。这将删除所有重复项,但会破坏元素的顺序:
list(set(a))
答案 1 :(得分:2)
首先,要删除重复项,请使用set:
>>> a = [1, 1, 4, 5, 6, 5]
>>> set(a)
{1, 4, 5, 6}
>>> list(set(a)) # if you really _need_ a list, you can convert it back
[1, 4, 5, 6]
其次,你得到的输出generator object unique at 0x...
意味着你有一个生成器对象,而不是一个简单的列表作为它的返回值。这是您在函数中使用yield
后应该期待的。 yield
将使任何函数成为生成器,并且如果您请求它们(或迭代它),它将仅为您提供所有结果。如果您只想获得完整结果,可以在对象上调用list()
以从生成器对象创建列表:list(unique(a))
。
但是,您会注意到函数给您的错误:TypeError: 'int' object is not subscriptable
。原因是你使用的value[0]
。 value
是列表中的元素(您遍历列表),因此是一个整数。您无法从整数中获取第一个元素,因此您可能只需要value
。
接下来,您将元素添加到found
,尽管您首先将列表定义为uni
,因此您应该决定其中一个名称。此外,该方法为append
,而非add
。
最后,你不应该再次在函数内部多次递归调用带有相同参数的方法,因为这只会填满堆栈而不提供任何用途,所以删除它的打印。
然后,你最终得到了这个,这很好用:
>>> def unique(a):
found = [] # better: use a set() here
for value in a:
if value not in found:
yield value
found.append(value)
>>> list(unique(a))
[1, 4, 5, 6]
但是,这仍然不是一个好的解决方案,你应该真的只使用set
,因为它还会为你提供进一步的方法来处理它的创建(例如快速检查包含性) )。
我还需要输入
来获得答案unique(a)
在这种情况下,只需从您的函数中删除yield value
,然后在结尾处返回found
列表。
答案 2 :(得分:2)
这是众所周知的经典之作:
>>> def unique(xs):
... seen = set()
... seen_add = seen.add
... return [x for x in xs if x not in seen and not seen_add(x)]
...
>>> unique([1, 2, 3, 3, 4, 1, 3, 5, 5, 4, 6])
[1, 2, 3, 4, 5, 6]
答案 3 :(得分:0)
通常的方法是list(set(a)
def unique(a):
return list(set(a))
现在,回答你的问题。 yield
返回一个必须迭代并且不打印的生成器。因此,如果您有一个函数,其中包含yield
,请像for return_value from function_that_yields():
一样迭代
您的问题还有更多问题。您尚未定义found
,然后索引可能不是容器的值。