从多个列表创建唯一对象列表

4 投票
3 回答
3568 浏览
提问于 2025-04-16 23:25

我定义了一个自定义对象,里面有多个字段。

比如说,我有一个学生对象,它包含了姓名、学号和年龄。为了比较两个学生,判断他们是否是同一个人,我实现了一个 __ eq__ 方法,这个方法会检查两个学生的年龄、姓名和学号是否一致。

def __eq__(self, other):
   return self.name == other.name and self.ID == other.ID and self.age == other.age

需要注意的是,学生只是一个例子,所以学生的学号通常是唯一的这一点不在讨论范围内。

假设我有以下的注册名单,里面有任意数量的学生对象。

[S1, S2, S3]
[S2, S3]
[S3, S5, S4]
[S1, S4, S2, S1]

我想创建一个数据结构,里面包含以下元素。

S1, S2, S3, S4, S5

最简单的方法就是初始化一个可以装很多东西的数据结构,取出一个项目,检查它是否已经存在于这个结构中,如果不存在就添加进去。

new_list = some_new_list 
for each list of students:
  for each student in the list:
     check if the student is in new_list
     #decide what to do 

如果我决定用一个简单的列表来实现,随着我的列表不断增长,我可能会进行很多比较,尤其是当我有大量学生和注册名单的时候。

有没有什么高效的方法来实现这个?既可以比较两个对象,又可以利用这个比较方法生成一个唯一的对象集合。

编辑:所以我尝试了一个简单的集合实现。

>>>a = Student("sample", 1234, 18)
>>>b = Student("sample", 1234, 18)
>>>students = set()
>>>students.add(a)
>>>b in students
False
>>>b == a
True

我是不是做错了什么?

3 个回答

-3

我只有一个词想告诉你。

集合

这里是关于集合的文档

0

set 这个东西不保证会保持顺序。如果你需要一个能保持顺序的列表:

import itertools
from typing import List

def unique_items(*lists: List) -> List:
    """Return an order-preserving list of unique items from the given lists.

    The implemented approach requires that the input items are hashable.

    Example: unique_items([1,9,4], [2,4,6,8,8], [3,1]) -> [1, 9, 4, 2, 6, 8, 3]

    Ref: https://stackoverflow.com/a/68626841/
    """
    return list(dict.fromkeys(itertools.chain(*lists)))
8
from itertools import chain
myset = set(chain(iterable1, iterable2, iterable3, iterable4))

你会得到一些独特的项目,而且每个可迭代对象只会被遍历一次。chain可以把一系列可迭代对象连接成一个长的可迭代对象。如果你需要排序,可以用sorted(myset)来得到一个排序后的列表。

你的Student类需要实现一个__hash__方法,这个方法要和它的__eq__方法兼容:

def __hash__(self):
    return (self.name, self.ID, self.age).__hash__()

撰写回答