从Python中的列表中筛选重复项

时间:2012-10-13 23:25:59

标签: python filter

我遇到了一个问题,我必须从列表这样的

中过滤掉dupes
a = [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

4 个答案:

答案 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,然后索引可能不是容器的值。