如何唯一的对象列表?

时间:2013-12-20 13:04:33

标签: python

如何在Python中使用唯一的对象列表,保存顺序?

def Test(object):
    def __init__(self,p1,p2):
        self.p1 = p1
        self.p2 = p2
lst = [Test(1,2), Test(2,3), Test(1,2)]

两个对象uniq,如果

Test1.p1 == Test2.p1 and Test1.p1 == Test2.p2

6 个答案:

答案 0 :(得分:5)

class Test(object):
    def __init__(self,p1,p2):
        self.p1 = p1
        self.p2 = p2

    def __eq__(self, other):
        return (other.p1 == self.p1) and (other.p2 == self.p2)

    def __hash__(self):
        return (self.p1 << 64) | self.p2

lst = [Test(1,2), Test(2,3), Test(1,2)]
from collections import OrderedDict
uniq = list(OrderedDict.fromkeys(lst, 0))
print [[item.p1, item.p2] for item in uniq]
  1. 如果我们使用hashable个集合中的对象,我们应该定义__hash____eq__个函数。

  2. 我使用(self.p1 << 64) | self.p2作为哈希值,假设数字p1p2不会超过2 ^ 64(18446744073709551616)。

  3. 这样可行,但不要这样做。您创建的类是可变的,这意味着可以更改对象的状态(基本上您将更改p1p2)。如果对象的状态可以更改,则哈希值也将更改。如您所见,我们依靠__hash__将对象存储在OrderedDict中。

答案 1 :(得分:1)

我正在改变我的答案以保持秩序。您可以定义相等(通过添加__eq__方法)并将您的项目逐个附加到新列表中,同时检查它们是否已存在:

class Test(object):
    def __init__(self,p1,p2):
        self.p1 = p1
        self.p2 = p2

    def __eq__(self, ot):
        return self.p1 == ot.p1 and self.p2 == ot.p2


lst = [Test(1,2), Test(2,3), Test(1,2)]
new_lst = []
for x in lst:
    if x not in new_lst:
        new_lst.append(x)

答案 2 :(得分:0)

使用collections.OrderedDict

class Test(object):
    def __init__(self, p1, p2):
        self.p1 = p1
        self.p2 = p2

lst = [Test(1,2), Test(2,3), Test(1,2)]


import collections
d = collections.OrderedDict()
for x in lst:
    key = x.p1, x.p2
    if key not in d:
        d[key] = x

for test_item in d.values():
    print(test_item.p1, test_item.p2)

打印

1 2
2 3

答案 3 :(得分:0)

或者,使用生成器跟踪已经使用集合显示的键:

def unique_values(iterable):
    seen = set()
    for value in iterator:
        key = (value.p1, value.p2)
        if key not in seen:
            yield value
            seen.add(key)

lst = list(unique_values(lst))

答案 4 :(得分:0)

作为列表理解的粉丝,我必须分享这篇文章:

seen = set()
uniq_list = [t for t in lst if (t.p1, t.p2) not in seen and not seen.add((t.p1, t.p2))]
  1. “(t.p1, t.p2) not in seen”对于新出现的情况是正确的,因此只有当它是新的时才继续下一部分。
  2. "not seen.add((t.p1, t.p2))" 始终为 True 并将元素添加到 seen 中。

答案 5 :(得分:-1)

你可以做一些感觉很讨厌的事,但应该适合你:

tmpset = set(lst)
uniqsorted = list(tmpset).sort()