Python字符串替换异常:多位数编号被拆分为个位数重复替换
问题描述
我在处理一份配送信息文件,每行格式为「姓名, 商品编号, 商品编号...」,示例内容:Joe, 2, 22, 10, 17。
尝试将商品编号替换为字典对应值时出现错误:编号22未被替换为对应的"Tandbørste",反而被替换成键2对应的"Snus"两次。我试过把字典的键改成字符串类型,问题仍未解决。
相关代码及测试文件内容如下:
import sys f = open("testFil.txt", "r") list_of_lists = [] items = { 1: "Cigaretter", 2: "Snus", 3: "Kaffe", 4: "Te", 5: "Solbriller", 6: "Mørk Chokolade", 7: "Kiks", 8: "Harebo Mix", 9: "Salt Chips", 10: "Pepper Chips", 11: "Sour Cream Chips", 12: "Oreo", 13: "Ritter Sport", 14: "Chokolade Kiks", 15: "Mælk", 16: "Sukker", 17: "Brød", 18: "Kuglepen", 19: "Juice", 20: "Avis", 21: "Toilet Papir", 22: "Tandbørste", 23: "Kondomer", 24: "Tandpasta", 25: "Køkkenrulle"} with open("testFil.txt", "r") as f: for line in f: line = line.replace("\n","") for i in items: line = line.replace(str(i), items[i]) list_of_lists.append(line.split(", ")) for i in list_of_lists: for j in i: if i.count(j) > 1: i[i.index(j)] = str(i.count(j)) + "x " + j for k in range(i.count(j)): i.remove(j) customer_count = -1 def last_customer(): print("This is the last order") print(list_of_lists[next_customer()]) def luk_programmet(): sys.exit() def next_customer(): global customer_count customer_count += 1 return customer_count def print_customer(): a = input("") if a == "Next Order": if customer_count == len(list_of_lists) - 2: print("This is the last order") print(list_of_lists[next_customer()]) luk_programmet() else: try: print(list_of_lists[next_customer()]) except IndexError: print("This is the last order") luk_programmet() elif a == "/close the program": luk_programmet() else: print("You typed it wrong.") print_customer() #Prints the customer list print("Write 'Next Order' to recieve the next order") for i in range(len(list_of_lists)): if print_customer() == "Done": sys.exit() print_customer()
测试文件testFil.txt内容:
Joe, 1, 2, 1, 8 Micky, 19, 19, 15, 13 Berta, 4, 3, 3, 3 Frede, 24, 22, 8, 2 per, 1, 9, 18, 24
错误原因
问题出在整行字符串循环替换的逻辑上:当你先把"2"替换成"Snus"后,原字符串中的"22"会被拆成两个独立的"2"。第一次替换第一个"2"得到"Snus2",后续遍历到"2"时又会替换剩余的"2",最终变成"SnusSnus"。此外,字典的遍历顺序若先处理小数字,会直接破坏大数字的结构,导致替换错误。
解决方案
正确的做法是先拆分每行内容,单独处理每个商品编号,而非直接在整行字符串上做全局替换。
步骤1:修改文件读取与编号转换逻辑
将整行替换改为拆分后逐个转换编号:
with open("testFil.txt", "r") as f: for line in f: line = line.strip("\n") parts = line.split(", ") name = parts[0] converted_items = [] for num_str in parts[1:]: # 将字符串编号转为整数,从字典取值,取不到则保留原编号 item_num = int(num_str) converted_items.append(items.get(item_num, num_str)) list_of_lists.append([name] + converted_items)
此方式可精准处理每个编号,避免字符串替换带来的误匹配问题。
步骤2:优化重复商品统计逻辑
原统计逻辑在修改列表时会因索引变化导致遗漏,改用字典统计更可靠:
processed_list = [] for order in list_of_lists: name = order[0] item_counts = {} for item in order[1:]: item_counts[item] = item_counts.get(item, 0) + 1 # 转换为带数量的格式 formatted_items = [f"{count}x {item}" if count > 1 else item for item, count in item_counts.items()] processed_list.append([name] + formatted_items) list_of_lists = processed_list
完整修正代码
import sys list_of_lists = [] items = { 1: "Cigaretter", 2: "Snus", 3: "Kaffe", 4: "Te", 5: "Solbriller", 6: "Mørk Chokolade", 7: "Kiks", 8: "Harebo Mix", 9: "Salt Chips", 10: "Pepper Chips", 11: "Sour Cream Chips", 12: "Oreo", 13: "Ritter Sport", 14: "Chokolade Kiks", 15: "Mælk", 16: "Sukker", 17: "Brød", 18: "Kuglepen", 19: "Juice", 20: "Avis", 21: "Toilet Papir", 22: "Tandbørste", 23: "Kondomer", 24: "Tandpasta", 25: "Køkkenrulle"} # 读取并转换订单 with open("testFil.txt", "r") as f: for line in f: line = line.strip("\n") parts = line.split(", ") name = parts[0] converted_items = [] for num_str in parts[1:]: item_num = int(num_str) converted_items.append(items.get(item_num, num_str)) list_of_lists.append([name] + converted_items) # 统计重复商品 processed_list = [] for order in list_of_lists: name = order[0] item_counts = {} for item in order[1:]: item_counts[item] = item_counts.get(item, 0) + 1 formatted_items = [f"{count}x {item}" if count > 1 else item for item, count in item_counts.items()] processed_list.append([name] + formatted_items) list_of_lists = processed_list customer_count = -1 def luk_programmet(): sys.exit() def next_customer(): global customer_count customer_count += 1 return customer_count def print_customer(): a = input("") if a == "Next Order": if customer_count == len(list_of_lists) - 2: print("这是最后一份订单") print(list_of_lists[next_customer()]) luk_programmet() else: try: print(list_of_lists[next_customer()]) except IndexError: print("这是最后一份订单") luk_programmet() elif a == "/close the program": luk_programmet() else: print("输入错误,请重新输入。") print_customer() # 启动程序 print("输入'Next Order'获取下一份订单") for _ in range(len(list_of_lists)): print_customer()
内容的提问来源于stack exchange,提问作者Mikkel
相关产品推荐
相关产品推荐

