【问题标题】:Creating unique list of objects from multiple lists从多个列表创建唯一的对象列表
【发布时间】:2011-10-25 07:04:21
【问题描述】:

我已经定义了一个包含多个字段的自定义对象。

例如,假设我有一个 Student 对象,它由姓名、ID 和年龄组成。为了比较两个学生并确定他们是否是同一个学生,我实现了一个 __ eq__ 方法,该方法将返回两个学生的年龄、姓名和 ID 是否匹配。

def __eq__(自我,其他): 返回 self.name == other.name 和 self.ID == other.ID 和 self.age == other.age

请记住,学生只是一个示例,因此不考虑学生 ID 往往是唯一的这一事实。

假设我有以下注册列表,其中包含任意数量的学生对象

[S1、S2、S3] [S2、S3] [S3、S5、S4] [S1、S4、S2、S1]

我想创建一些包含以下元素的数据结构

S1、S2、S3、S4、S5

最简单的方法是初始化一些可以容纳很多东西的数据结构,抓取一个项目,检查它是否存在于结构中,如果不存在则添加它。

new_list = some_new_list 对于每个学生列表: 对于列表中的每个学生: 检查学生是否在 new_list #决定做什么

如果我决定将它作为一个简单的列表来实现,随着我的列表继续增长,我可能会进行大量比较,尤其是当我有大量的学生和注册列表时。

什么是实现这一点的有效方法?两者都用于比较两个对象,然后使用该比较方法生成一组唯一的对象。

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

>>>a = Student("样本", 1234, 18) >>>b = Student("样本", 1234, 18) >>>学生=设置() >>>students.add(a) >>>b 在学生 错误的 >>>b == a 真的

我做错了吗?

【问题讨论】:

  • 为什么不用内置的set类型呢?成员资格测试可能比您在纯 Python 中所希望的更有效。
  • @omrib,所以遍历每个学生列表,然后调用 newSet.add(student) 是否尽可能好?
  • @agf,哦,我以为只检查一个项目是否存在于集合中就足够了。即:“成员资格测试”
  • 你没有来检查他们是否在集合中。只需将它们全部添加,该集合最终将包含唯一条目。这比单独检查一个是否唯一要快。查看我对__hash__的编辑
  • @agf,大概就是这样。但是,当我实现哈希方法并尝试使用相同名称 ID 和年龄(即:同一个学生)的两个不同学生对象时,它们都被添加到集合中。

标签: python performance


【解决方案1】:
from itertools import chain
myset = set(chain(iterable1, iterable2, iterable3, iterable4))

您会获得独特的项目,并且您只对每个可迭代对象进行一次迭代。 chain 从一系列可迭代对象中生成一个长可迭代对象。如果你需要排序,sorted(myset) 会给你一个排序列表。

您的Student 类需要实现一个与其__eq__ 兼容的__hash__

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

【讨论】:

  • 如果您有可变数量的学生列表(全部包含在名为student_lists 的列表或元组中),您可以使用set(chain(*student_lists))
  • @omrib 使用set(chain.from_iterable(student_lists)),所以student_lists 不必解压。写itertools.chain 的人想到了这一点,不像mapzip 这样的东西。
【解决方案2】:

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)))

【讨论】:

    【解决方案3】:

    我只有一个字要告诉你。

    设置

    Here are the docs for sets

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-26
      • 1970-01-01
      • 1970-01-01
      • 2017-06-26
      • 2014-09-25
      相关资源
      最近更新 更多