【问题标题】:Python: Merge two list of diferent objects by attributePython:按属性合并两个不同对象的列表
【发布时间】:2022-11-15 20:13:11
【问题描述】:

我试图找到一种有效的方法来合并两个具有不同结构的 python 对象(类)列表,并将它们合并到一个新的新对象列表中。编码:

from datetime import datetime


class StructureOne(object):
    def __init__(self, date_time: datetime, name: str):
        self.date_time: datetime = date_time
        self.name: str = name
        self.value = None

    def set_value(self,value:float):
        self.value = value


class StructureTwo(object):
    def __init__(self, date_time: datetime, value: float):
        self.date_time = date_time
        self.value: float = value


def merge_lists(list_one: list[StructureOne], list_two: list[StructureTwo]) -> list[StructureOne]:
    for element_one in list_one:
        i = 0
        while i < len(list_two) and element_one.value is not None:
            if element_one.date_time == list_two[i].date_time:
                element_one.set_value(value=list_two[i].value)
            i += 1
    return list_one


list_one: list[StructureOne] = [
    StructureOne(date_time=datetime(2022, 1, 1, 0), name='zero'),
    StructureOne(date_time=datetime(2022, 1, 1, 1), name='one'),
    StructureOne(date_time=datetime(2022, 1, 1, 2), name='two'),
    StructureOne(date_time=datetime(2022, 1, 1, 3), name='three'),
]

list_two: list[StructureTwo] = [
    StructureTwo(date_time=datetime(2022, 1, 1, 0), value=0),
    StructureTwo(date_time=datetime(2022, 1, 1, 1), value=1),
    StructureTwo(date_time=datetime(2022, 1, 1, 2), value=2),
    StructureTwo(date_time=datetime(2022, 1, 1, 3), value=3),
]


merged_list: list[StructureOne] = merge_lists(list_one=list_one, list_two=list_two)

期望的结果是


list_one: list[StructureOne] = [
    StructureOne(date_time=datetime(2022, 1, 1, 0), name='zero', value=0),
    StructureOne(date_time=datetime(2022, 1, 1, 1), name='one', value=1),
    StructureOne(date_time=datetime(2022, 1, 1, 2), name='two', value=2),
    StructureOne(date_time=datetime(2022, 1, 1, 3), name='three', value=3),
]

我们试图不使用像py-linq 这样的外部库。

【问题讨论】:

  • merge_lists 方法的当前实现只是返回list_one,作为你的集合value = None,并且永远不会改变它的值。
  • 你想要的输出是什么?你打算如何解决日期不匹配的问题?您只对将 list_two 中的 value 添加到 list_one 中的元素感兴趣?

标签: python


【解决方案1】:

假设:

  • 列表可能未排序。
  • date_time 字段在每个列表中是唯一的。
  • 如果输出已排序,则可以。
  • 您想在匹配date_time 时使用来自list_two 中的对象的value 填充list_one 中的对象的value
  • 您只想填充 list_one 中对象的 value,如果它是 None
  • 在您的代码中,如果 valuenot None,您只填充它;我假设你想做相反的事情。
def merge_lists(list_one: list[StructureOne], list_two: list[StructureTwo]) -> list[StructureOne]:

    # sort lists by date_time
    list_1 = sorted(list_one, key=lambda x: x.date_time)
    list_2 = sorted(list_two, key=lambda x: x.date_time)

    # merge sort
    i, j = 0, 0
    while i < len(list_1) and j < len(list_2):
        if list_1[i].date_time < list_2[j].date_time:
            i += 1
        elif list_1[i].date_time > list_2[j].date_time:
            j += 1
        else:
            # date_time matches
            # populate value from list_two into list_one if value is None
            if list_1[i].value is None:
                list_1[i].value = list_2[j].value
            i += 1
            j += 1

    return list_1

【讨论】:

    【解决方案2】:

    如果你只想按每个列表的顺序将StructureOnevalue属性更改为StructureTwovalue,那么你可以这样做来修改list_one中的元素:

    for elem_one, elem_two in zip(list_one,list_two):
        elem_one.value = elem_two.value
    

    您甚至不需要在 StructureOne 中包含 value 属性,它的工作原理是一样的:

    class StructureOne(object):
        def __init__(self, date_time: datetime, name: str):
            self.date_time: datetime = date_time
            self.name: str = name
    

    如果通过合并你的意思是摆脱list_two,你可以删除变量,这样它就会被丢弃。

    del list_two
    

    合并后打印元素将更新您的值成员:

    for e in list_one:
        print(e.date_time,e.name,e.value)
    
    # Output:
    
    2022-01-01 00:00:00 zero 0
    2022-01-01 01:00:00 one 1
    2022-01-01 02:00:00 two 2
    2022-01-01 03:00:00 three 3
    

    您的 __init__ 函数在名称上有很多重复,这就是为什么使用 dataclasses 是个好主意,它的工作原理相同,但更易于阅读和维护:

    from dataclasses import dataclass
    
    @dataclass
    class StructureOne:
        date_time : datetime.datetime
        name : str
    
    @dataclass
    class StructureTwo:
        date_time : datetime.datetime
        value : float
    

    【讨论】:

      【解决方案3】:

      你试过 py_linq 或其他图书馆吗?

      谢谢

      【讨论】:

      • 欢迎来到 StackOverflow——后续问题应作为 cmets 发布,而不是答案。我知道您在达到某个代表之前不能发表评论,但请尝试回答一两个问题。 OP 还明确写道他们不想使用 py_linq
      • “我们试图不使用像 py_linq 这样的外部库”
      猜你喜欢
      • 1970-01-01
      • 2021-09-10
      • 1970-01-01
      • 2022-10-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多