有两个列表:
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
]
但是随着列表数量的增加,将花费大量时间,如何以最有效的方式合并这些列表?
答案 0 :(得分:2)
这里的问题是您使用了错误的数据结构来存储数据。您需要将它们存储在python字典中。每当您进行基于项目的查找时,请使用python字典。
那就用
代替列表l2l2 = {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
。id
是Python中的保留名称;我们使用id_
。None
。lst2
(请参阅@Aish Sharma的答案)。