字典列表重复id生成唯一id的代码错误排查与优化
问题描述
我有一个包含id键的字典列表,部分id存在重复。我不想删除重复项,而是要在原id基础上递增生成新的唯一id,且新id不能和当前所有id(包括已生成的新id)重复。但运行以下代码后,仍存在重复id:
初始代码
import copy ids = [{'id': 44},{'id': 49},{'id': 48},{'id': 53},{'id': 46},{'id': 51},{'id': 45},{'id': 50},{'id': 47},{'id': 52},{'id': 5091},{'id': 5060},{'id': 5002},{'id': 5071},{'id': 5011},{'id': 5027},{'id': 26},{'id': 29},{'id': 5034},{'id': 5086},{'id': 5063},{'id': 5022},{'id': 5014},{'id': 74},{'id': 5061},{'id': 4},{'id': 5013},{'id': 5076},{'id': 5055},{'id': 5006},{'id': 5051},{'id': 5032},{'id': 5008},{'id': 14},{'id': 35},{'id': 5},{'id': 7},{'id': 64},{'id': 5049},{'id': 5021},{'id': 5059},{'id': 5029},{'id': 6},{'id': 30},{'id': 23},{'id': 31},{'id': 5017},{'id': 8},{'id': 17},{'id': 24},{'id': 5007},{'id': 5033},{'id': 5065},{'id': 5020},{'id': 5085},{'id': 5025},{'id': 5068},{'id': 5041},{'id': 5048},{'id': 5056},{'id': 5080},{'id': 5070},{'id': 5072},{'id': 5077},{'id': 5073},{'id': 5067},{'id': 5088},{'id': 5010},{'id': 5040},{'id': 5075},{'id': 5035},{'id': 5043},{'id': 5012},{'id': 5052},{'id': 5081},{'id': 5004},{'id': 57},{'id': 56},{'id': 63},{'id': 62},{'id': 55},{'id': 54},{'id': 22},{'id': 59},{'id': 58},{'id': 61},{'id': 60},{'id': 21},{'id': 5046},{'id': 5024},{'id': 5036},{'id': 5058},{'id': 5053},{'id': 5044},{'id': 38},{'id': 36},{'id': 5050},{'id': 5047},{'id': 5079},{'id': 5062},{'id': 37},{'id': 13},{'id': 3},{'id': 27},{'id': 5078},{'id': 5009},{'id': 5069},{'id': 5092},{'id': 5090},{'id': 66},{'id': 81},{'id': 82},{'id': 70},{'id': 67},{'id': 75},{'id': 78},{'id': 76},{'id': 5001},{'id': 68},{'id': 69},{'id': 79},{'id': 65},{'id': 71},{'id': 77},{'id': 73},{'id': 72},{'id': 5031},{'id': 5083},{'id': 5037},{'id': 5003},{'id': 15},{'id': 16},{'id': 25},{'id': 32},{'id': 5023},{'id': 2},{'id': 5038},{'id': 5030},{'id': 5019},{'id': 5087},{'id': 5089},{'id': 5082},{'id': 5028},{'id': 5054},{'id': 5074},{'id': 5018},{'id': 5015},{'id': 5064},{'id': 5045},{'id': 5057},{'id': 5084},{'id': 5026},{'id': 5016},{'id': 12},{'id': 11},{'id': 10},{'id': 5066},{'id': 5042},{'id': 5005},{'id': 28},{'id': 80},{'id': 17131},{'id': 6646},{'id': 6440},{'id': 11253},{'id': 6254},{'id': 6240},{'id': 10547},{'id': 10495},{'id': 8179},{'id': 8139},{'id': 10726},{'id': 17285},{'id': 6566},{'id': 10760},{'id': 16521},{'id': 10732},{'id': 17627},{'id': 10179},{'id': 17433},{'id': 17437},{'id': 17435},{'id': 6554},{'id': 6560},{'id': 6562},{'id': 6664},{'id': 12507},{'id': 12509},{'id': 11275},{'id': 6606},{'id': 17287},{'id': 17289},{'id': 12511},{'id': 12221},{'id': 8705},{'id': 17129},{'id': 8691},{'id': 11078},{'id': 11697},{'id': 6604},{'id': 6590},{'id': 17413},{'id': 17217},{'id': 11076},{'id': 10724},{'id': 11487},{'id': 5188},{'id': 6049},{'id': 6556},{'id': 6558},{'id': 6700},{'id': 6548},{'id': 5437},{'id': 4},{'id': 6244},{'id': 5061},{'id': 10085},{'id': 12707},{'id': 35},{'id': 64},{'id': 18003},{'id': 6442},{'id': 6710},{'id': 12709},{'id': 11255},{'id': 11273},{'id': 17279},{'id': 17277},{'id': 17975},{'id': 16981},{'id': 6676},{'id': 6550},{'id': 6842},{'id': 37},{'id': 11054},{'id': 5444},{'id': 6426},{'id': 70},{'id': 67},{'id': 75},{'id': 6234},{'id': 8880},{'id': 8899},{'id': 13835},{'id': 14759},{'id': 7112},{'id': 5017},{'id': 6236},{'id': 9923},{'id': 16817},{'id': 5228},{'id': 5029}] aID = copy.deepcopy(ids) uniques = set([ x.get('id') for x in ids ]) listOf = [ x.get('id') for x in ids ] G = True d= 0 for items in aID: if items.get('id') in uniques and listOf.count(items.get('id')) > 1: G = True while(G): d += 1 if(items.get('id') + d not in uniques): items.update({'id': items.get('id')+ d}) G = False else: continue
运行后检查重复id,仍存在重复情况(输出的重复计数列表显示多个重复)。
我尝试了以下代码,在样本数据中有效,但担心在实际数据集会产生重复:
aID = copy.deepcopy(ids) uniques = set() for item in aID: d = 0 while item['id'] + d in uniques: d += 1 item['id'] += d uniques.add(item['id']) while items.get('id') + d not in uniques: d+=1 items.update({'id':items.get('id')+d}) break
请问初始代码哪里出错了?
初始代码错误分析
- 全局变量
d导致计算混乱:d在循环外初始化,每次处理重复项时会累加之前的数值,不是每个item单独从0开始计算偏移量。比如第一个重复项用了d=1,下一个重复项直接从d=2开始,可能生成的偏移量完全不符合需求,甚至和其他新生成的id重复。 uniques集合未实时更新:uniques只存储了原始的id,没有把修改后的新id加入进去。当生成新id后,后续的item可能会生成和这个新id重复的值,因为集合里没有记录。- 重复判断逻辑失效:判断条件
items.get('id') in uniques and listOf.count(items.get('id')) > 1中,当第一个重复项被修改后,它的id已经不在原始uniques里了,但listOf是原始id的列表,count结果还是大于1,会导致后续同原始id的item进入处理逻辑,但此时d已经是累加后的数值,计算出的新id大概率会出错。
另外,你尝试的第二个代码里有多余的错误逻辑:最后一个while循环用了未定义的items(应该是item),而且这个循环完全没必要,反而会无端修改已经生成好的唯一id,导致重复。
正确实现方案
保留第二个代码的核心逻辑,去掉多余的错误循环,就能保证生成的id完全唯一:
import copy ids = [{'id': 44}, ...] # 你的原始数据列表 aID = copy.deepcopy(ids) uniques = set() for item in aID: d = 0 # 从0开始找第一个未被使用的偏移量 while item['id'] + d in uniques: d += 1 # 更新当前item的id new_id = item['id'] + d item['id'] = new_id # 将新id加入集合,确保后续不会重复使用 uniques.add(new_id)
逻辑说明
- 每个item单独初始化
d=0,保证每个重复项都从原id开始递增找可用值。 uniques集合实时更新,每次生成新id后立即加入,确保后续所有item都不会使用已存在的id(包括原始id和新生成的id)。- 没有多余的逻辑,每一步都只做必要的操作,完全避免重复。
内容的提问来源于stack exchange,提问作者Dollar Tune-bill
相关产品推荐
相关产品推荐

