Python 中的循环和条件
For loops and conditionals in Python
我是 Python 的新手,我想知道是否有办法 shorten/optimise 以下循环:
for breakdown in data_breakdown:
for data_source in data_source_ids:
for camera in camera_ids:
if (camera.get("id") == data_source.get("parent_id")) and (data_source.get("id") == breakdown.get('parent_id')):
for res in result:
if res.get("camera_id") == camera.get("id"):
res.get('data').update({breakdown.get('name'): breakdown.get('total')})
我试过这个 oneliner,但它似乎不起作用:
res.get('data').update({breakdown.get('name'): breakdown.get('total')}) for camera in camera_ids if (camera.get("id") == data_source.get("parent_id")) and (data_source.get("id") == breakdown.get('parent_id'))
您可以使用 itertools.product
为您处理嵌套循环,我认为(虽然我不确定,因为我看不到您的数据)您可以跳过所有 .get
和 .update
并仅使用 []
运算符:
from itertools import product
for b, d, c in product(data_breakdown, data_source_ids, camera_ids):
if c["id"] != d["parent_id"] or d["id"] != b["parent_id"]:
continue
for res in result:
if res["camera_id"] == c["id"]:
res['data'][b['name']] = b['total']
如果有的话,要优化这些循环的 性能 ,您应该使它们更长且嵌套更多,data_source.get("id") == breakdown.get('parent_id')
发生在 [=13= 之外]循环。
但也许还有一个替代方案,您可以在其中更改数据的结构,这样您就不需要尽可能多地循环来查找匹配的 ID 值。将您当前的每个列表(字典)转换为一个字典,其键等于您将在该循环中尝试匹配的 'id'
值,并且该值为整个字典。
sources_dict = {source.get("id"): source for source in data_source_ids}
cameras_dict = {camera.get("id"): camera for camera in camera_ids}
results_dict = {res.get("camera_id"): res for res in result}
现在整个循环只需要一层:
for breakdown in data_breakdown:
source = sources_dict[breakdown["parent_id"]]
camera = cameras_dict[source["parent_id"]]
res = results_dict[camera["id"]]
res.data[breakdown["name"]] = breakdown["total"]
此代码假定您当前代码中带有 get
的所有查找都将成功获取值。您实际上并没有检查从 get
调用中获得的任何值是否为 None
,因此它可能没有太大好处。
我还要指出,尚不清楚原始代码中的 camera
循环是否完全必要。您可能已经能够跳过它并直接将 data_source['parent_id']
与 res['camera_id']
进行比较,而无需将它们都与两者之间的 camera['id']
进行比较。在我的更新版本中,这将转化为省略 cameras_dict
的创建并直接使用 source["parent_id"]
索引 results_dict
而不是首先索引以查找 camera
。
我是 Python 的新手,我想知道是否有办法 shorten/optimise 以下循环:
for breakdown in data_breakdown:
for data_source in data_source_ids:
for camera in camera_ids:
if (camera.get("id") == data_source.get("parent_id")) and (data_source.get("id") == breakdown.get('parent_id')):
for res in result:
if res.get("camera_id") == camera.get("id"):
res.get('data').update({breakdown.get('name'): breakdown.get('total')})
我试过这个 oneliner,但它似乎不起作用:
res.get('data').update({breakdown.get('name'): breakdown.get('total')}) for camera in camera_ids if (camera.get("id") == data_source.get("parent_id")) and (data_source.get("id") == breakdown.get('parent_id'))
您可以使用 itertools.product
为您处理嵌套循环,我认为(虽然我不确定,因为我看不到您的数据)您可以跳过所有 .get
和 .update
并仅使用 []
运算符:
from itertools import product
for b, d, c in product(data_breakdown, data_source_ids, camera_ids):
if c["id"] != d["parent_id"] or d["id"] != b["parent_id"]:
continue
for res in result:
if res["camera_id"] == c["id"]:
res['data'][b['name']] = b['total']
如果有的话,要优化这些循环的 性能 ,您应该使它们更长且嵌套更多,data_source.get("id") == breakdown.get('parent_id')
发生在 [=13= 之外]循环。
但也许还有一个替代方案,您可以在其中更改数据的结构,这样您就不需要尽可能多地循环来查找匹配的 ID 值。将您当前的每个列表(字典)转换为一个字典,其键等于您将在该循环中尝试匹配的 'id'
值,并且该值为整个字典。
sources_dict = {source.get("id"): source for source in data_source_ids}
cameras_dict = {camera.get("id"): camera for camera in camera_ids}
results_dict = {res.get("camera_id"): res for res in result}
现在整个循环只需要一层:
for breakdown in data_breakdown:
source = sources_dict[breakdown["parent_id"]]
camera = cameras_dict[source["parent_id"]]
res = results_dict[camera["id"]]
res.data[breakdown["name"]] = breakdown["total"]
此代码假定您当前代码中带有 get
的所有查找都将成功获取值。您实际上并没有检查从 get
调用中获得的任何值是否为 None
,因此它可能没有太大好处。
我还要指出,尚不清楚原始代码中的 camera
循环是否完全必要。您可能已经能够跳过它并直接将 data_source['parent_id']
与 res['camera_id']
进行比较,而无需将它们都与两者之间的 camera['id']
进行比较。在我的更新版本中,这将转化为省略 cameras_dict
的创建并直接使用 source["parent_id"]
索引 results_dict
而不是首先索引以查找 camera
。