如何合并这两个列表?

时间:2019-06-24 10:49:22

标签: python list

有两个列表:


l1 = [
{"name":"name_1", "id":"1231"},
...,
{"name":"name_10000", "id":"13113"},
...
]


# list of class A's instance
l2 =[
<__main__.A object at 0x000001F23FDFCE10>,
<__main__.A object at 0x000001F23FDFCEB8>,
...
<__main__.A object at 0x000001F23FDFCEB8>,
]



# For example
class A:
    def __init__(self, id, status):
        self.id = id
        self.status = status

l2 = [
    A(item, "status_{}".format(item)) for item in range(1, 10000)
]

我想基于l1合并这两个列表,并创建一个新列表,如:

l3 = [

{"id": "2313", "name":"name_2313", "status":"status_2313"},
...

{"id": "xxx", "name":"name_xxx", "status":"status_xxx"},

# if there's no match in l2, then the result should be 
{"id": "xxx", "name":"name_xxx", "status": None},

]

我尝试了以下列表理解:


l3 = [
        {
            "id": item["id"],
            "name": item["name"],
            "status": stat.status if stat.id == item['id'] else None,

        }
    for item in l1 for stat in l2
 ]

但是随着列表数量的增加,将花费大量时间,如何以最有效的方式合并这些列表?

2 个答案:

答案 0 :(得分:2)

这里的问题是您使用了错误的数据结构来存储数据。您需要将它们存储在python字典中。每当您进行基于项目的查找时,请使用python字典。

那就用

代替列表l2
l2 = {item: A(item, "status_{}".format(item)) for item in ("1231", "13113")}

(我仅以两个元素为例)

现在您获得了项目:实例对

{'1231': <__main__.A object at 0x10a8b6470>, '13113': <__main__.A object at 0x10a8b65c0>}
在此l3之后的

将仅是一个循环。

>>> l1 = [
... {"name":"name_1", "id":"1231"},
... {"name":"name_10000", "id":"13113"}
... ]
>>> l3 = [{**i, "status": l2.get(i["id"]).status} for i in l1]
>>> l3
[{'name': 'name_1', 'id': '1231', 'status': 'status_1231'}, {'name': 'name_10000', 'id': '13113', 'status': 'status_13113'}]

我们仍然面临一个问题。如果l2没有该ID怎么办?为此,我们可以使用状态返回None的伪类

>>> class Dummy:
...     def __init__(self):
...         self.status = None
... 
>>> l1 = [
... {"name":"name_1", "id":"12"},
... {"name":"name_10000", "id":"13113"}
... ]
>>> 
>>> l2 = {item: A(item, "status_{}".format(item)) for item in ("1231", "13113")}
>>> 
>>> l3 = [{**i, "status": l2.get(i["id"], Dummy()).status} for i in l1]
>>> l3
[{'name': 'name_1', 'id': '12', 'status': None}, {'name': 'name_10000', 'id': '13113', 'status': 'status_13113'}]

请参见此处,我们使用get,因为如果第一个参数不存在,则get返回第二个争论值。

奖金。

如果您从某处获取l2的数据,则可以执行一个循环将l2转换为字典,如我所示,然后按照同样的步骤进行操作。这样,您只需执行两个单循环而不是嵌套循环。

此后,如果您遇到问题,请告诉我。

答案 1 :(得分:1)

假设:您希望使用l1中对象的状态来更新l2中的新字典。

给出

一堂课。方便地,我们使用一个简单的数据类:

import dataclasses as dc


@dc.dataclass
class A:
    id_: int
    status: str

更简单的字典列表:

lst1 = [
    {"name":"name_0", "id_":0},
    {"name":"name_1", "id_":1},
    {"name":"name_2", "id_":2},
    {"name":"name_3", "id_":3},
]

A个对象的简短列表:

lst2 = [A(i, f"status_{i}") for i in range(3)]
lst2
# [A(id_=0, status='status_0'),
#  A(id_=1, status='status_1'),
#  A(id_=2, status='status_2')]

代码

进行查询,以减少循环。在这里,我们将ID与lst2中对象的状态进行映射:

lookup = {a.id_: a.status  for a in lst2}
lookup
# {0: 'status_0', 1: 'status_1', 2: 'status_2'}

将字典与查找值合并:

[{**d, **dict(status=lookup.get(d["id_"], None))} for d in lst1]
#[{'name': 'name_0', 'id_': 0, 'status': 'status_0'},
# {'name': 'name_1', 'id_': 1, 'status': 'status_1'},
# {'name': 'name_2', 'id_': 2, 'status': 'status_2'},
# {'name': 'name_3', 'id_': 3, 'status': None}]

注释

  • 数据类具有清晰的表示,但普通类可以替代数据类。
  • 由于l可以与1混淆,所以使用lst
  • Similary,id是Python中的保留名称;我们使用id_
  • 如果查找失败,默认状态为None
  • 此方法假定“有两个列表:”;否则,请做一个决定而不是lst2(请参阅@Aish Sharma的答案)。