You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python双循环删除字典元素时出现KeyError的问题及解决需求

问题:清理字典中1小时内值重复的元素(保留最早项)

需求

删除键为datetime类型、值为字符串类型的字典中,1小时内值相同的重复元素,仅保留最早的一个。

原代码问题

现有代码执行时会触发KeyError——部分符合条件的元素被删除后,外层循环仍会遍历已删除的键,导致访问不存在的键:

#del duplicates within 60min
for formatted_key in list(formatted_dict.keys()):
    for temp_key in list(formatted_dict.keys()):
        print("formatted_key:", formatted_key)
        print("temp_key:", temp_key)
        if(formatted_dict[formatted_key]==formatted_dict[temp_key]):
            if(temp_key!=formatted_key):
                td=timedelta(minutes = 60)
                new_key=formatted_key+td
                if (new_key>temp_key):
                    del formatted_dict[temp_key]
                    print("key to delet:", temp_key)
                    for key,value in formatted_dict.items():
                        print(key,value)

错误信息

if(formatted_dict[formatted_key]==formatted_dict[temp_key]):
KeyError: datetime.datetime(2022, 10, 25, 8, 16, 12, 286000)

测试数据

2022-10-25 08:14:08.820000 var301533
2022-10-25 08:16:12.286000 var301533
2022-10-25 08:17:05.067000 var003907
2022-10-25 08:19:04.422000 var003907
2022-10-25 08:20:05.021000 var301504
2022-10-25 08:23:04.526000 var301504
2022-10-25 08:23:14.204000 var301504

预期结果

2022-10-25 08:14:08.820000 var301533
2022-10-25 08:17:05.067000 var003907
2022-10-25 08:20:05.021000 var301504

解决方案

核心思路:按时间顺序遍历条目,记录每个值最近保留的时间点,批量删除符合删除条件的键,避免遍历过程中修改字典结构引发异常。

修正后代码

from datetime import datetime, timedelta

def clean_duplicates_within_hour(input_dict):
    # 按时间升序排序字典的键,确保先处理最早的条目
    sorted_keys = sorted(input_dict.keys())
    # 记录每个值最近一次被保留的时间
    value_last_kept = {}
    keys_to_delete = []
    
    for key in sorted_keys:
        current_value = input_dict[key]
        if current_value in value_last_kept:
            # 计算当前条目与同值已保留条目的时间差
            time_diff = key - value_last_kept[current_value]
            if time_diff <= timedelta(minutes=60):
                # 时间间隔在1小时内,标记为待删除
                keys_to_delete.append(key)
            else:
                # 超过1小时,更新该值的最近保留时间
                value_last_kept[current_value] = key
        else:
            # 首次出现该值,记录其时间
            value_last_kept[current_value] = key
    
    # 批量删除所有标记的键,避免遍历中修改字典导致的异常
    for key in keys_to_delete:
        del input_dict[key]
    return input_dict

# 构造测试字典(已转为datetime键)
formatted_dict = {
    datetime(2022, 10, 25, 8, 14, 8, 820000): "var301533",
    datetime(2022, 10, 25, 8, 16, 12, 286000): "var301533",
    datetime(2022, 10, 25, 8, 17, 5, 67000): "var003907",
    datetime(2022, 10, 25, 8, 19, 4, 422000): "var003907",
    datetime(2022, 10, 25, 8, 20, 5, 21000): "var301504",
    datetime(2022, 10, 25, 8, 23, 4, 526000): "var301504",
    datetime(2022, 10, 25, 8, 23, 14, 204000): "var301504",
}

# 执行清理并打印结果
cleaned_dict = clean_duplicates_within_hour(formatted_dict)
for key, value in sorted(cleaned_dict.items()):
    print(f"{key} {value}")

方案说明

  1. 排序键:先按时间升序排列所有键,确保最早的条目被优先处理并保留。
  2. 记录保留时间:用value_last_kept字典跟踪每个值最近一次被保留的时间,避免重复比较。
  3. 批量删除:先收集所有需要删除的键,最后统一删除,避免遍历字典过程中修改其结构,彻底解决KeyError问题。
  4. 准确的时间判断:直接计算当前条目与同值已保留条目的时间差,判断是否在1小时内,逻辑更清晰准确。

内容的提问来源于stack exchange,提问作者Max

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 18:43:12