【问题标题】:For loops and conditionals in PythonPython中的for循环和条件
【发布时间】:2022-01-01 12:31:54
【问题描述】:

我是 Python 新手,我想知道是否有办法缩短/优化以下循环:

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

【问题讨论】:

    标签: python loops conditional-statements


    【解决方案1】:

    您可以使用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']
    

    【讨论】:

    • 嗨,山姆!我使用 itertools 进行了一些调整,现在它可以工作了。下面的代码:对于产品中的 b、d、c(data_breakdown、data_source_ids、camera_ids):如果 c["id"] == d["parent_id"] 和 d["id"] == b["parent_id"]:对于 res 结果: if res["camera_id"] == c["id"]: res['data'][b['name']] = b['total'] 非常感谢!
    【解决方案2】:

    如果有的话,要优化这些循环的性能,您应该使它们更长、更嵌套,data_source.get("id") == breakdown.get('parent_id') 发生在camera 循环之外。

    但也许还有另一种选择,您可以更改数据的结构,这样您几乎不需要循环来查找匹配的 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

    【讨论】:

    • 完美运行并具有更好的性能!另外,您对相机循环的看法是正确的。谢谢!
    猜你喜欢
    • 2019-06-04
    • 2013-03-09
    • 1970-01-01
    • 2019-04-17
    • 1970-01-01
    • 2013-08-14
    • 2012-10-20
    • 2018-08-02
    • 2018-01-24
    相关资源
    最近更新 更多