Python字典添加元素后输出顺序混乱,OrderedDict无效求解决
Hey there! Let's fix your order issue and optimize your code at the same time.
Why Your Order Is Messed Up
The root problem here is that you're using a regular Python dict. Before Python 3.7, standard dictionaries don't preserve the order of inserted keys—this is why your output shows jumbled keys as you add more entries. Even in Python 3.7+, your current code prints the entire dictionary every time, which isn't what you want for your expected output.
Fixing the Order Issue
First, switch to OrderedDict from the collections module to guarantee insertion order (this works for all Python versions). If you're on Python 3.7+, you could stick with a regular dict, but OrderedDict makes your intent explicit for anyone reading the code.
Here's how to adjust your core code:
from collections import OrderedDict import os import glob src_path = r"C:\Users\username\Downloads\LITIV_dataset" # Use OrderedDict instead of regular dict newgtdict = OrderedDict() for folderName in os.listdir(src_path): folderPath = os.path.join(src_path, folderName) # Safer path joining if not os.path.isdir(folderPath): continue # Use os.path.join for glob pattern too listOfFilePaths = glob.glob(os.path.join(folderPath, f"{folderName}_GT.txt")) for filePath in listOfFilePaths: # Use 'with' statement to auto-close files with open(filePath, 'r') as openedFile: lines = openedFile.readlines() linecount = 0 for line in lines: linecount += 1 linenumber = str(linecount) line = line.strip() # Skip empty lines properly if not line: continue my_list = line.split(",") x_br = int(my_list[2]) y_br = int(my_list[3]) x_tl = int(my_list[0]) - (x_br // 2) # Integer division to avoid floats y_tl = int(my_list[1]) - (y_br // 2) box = [x_tl, y_tl, x_br, y_br] current_key = f"{filePath}{linenumber}" newgtdict[current_key] = box # Print only the current entry instead of the whole dict print({current_key: box})
This will give you the ordered, single-entry output you're expecting.
Better Optimizations for Your Code
If you want cleaner, more efficient code, here are some upgrades:
1. Use pathlib for Path Handling (Python 3.4+)
pathlib makes path operations way more readable and less error-prone:
from collections import OrderedDict from pathlib import Path src_path = Path(r"C:\Users\username\Downloads\LITIV_dataset") newgtdict = OrderedDict() for folder in src_path.iterdir(): if not folder.is_dir(): continue # Find the GT file directly with pathlib's glob gt_files = list(folder.glob(f"{folder.name}_GT.txt")) for gt_file in gt_files: with gt_file.open('r') as f: # Use enumerate to get line numbers automatically for line_num, line in enumerate(f, start=1): line = line.strip() if not line: continue # Unpack values directly instead of using a list x_tl_old, y_tl_old, x_br, y_br = map(int, line.split(",")) x_tl = x_tl_old - (x_br // 2) y_tl = y_tl_old - (y_br // 2) box = [x_tl, y_tl, x_br, y_br] key = f"{str(gt_file)}{line_num}" newgtdict[key] = box print({key: box})
2. Skip the Dictionary Entirely (If You Just Need to Write New Files)
If your end goal is to write modified bounding boxes to new files, you don't need to store everything in a dictionary—you can process and write lines on the fly, saving memory (especially for large datasets):
from pathlib import Path src_path = Path(r"C:\Users\username\Downloads\LITIV_dataset") for folder in src_path.iterdir(): if not folder.is_dir(): continue gt_files = list(folder.glob(f"{folder.name}_GT.txt")) for gt_file in gt_files: # Create a new file name (e.g., jp1_GT_new.txt) new_gt_file = gt_file.parent / f"{gt_file.stem}_new{gt_file.suffix}" # Read from original and write to new file in one go with gt_file.open('r') as f_in, new_gt_file.open('w') as f_out: for line in f_in: line = line.strip() if not line: f_out.write("\n") continue x_tl_old, y_tl_old, x_br, y_br = map(int, line.split(",")) x_tl = x_tl_old - (x_br // 2) y_tl = y_tl_old - (y_br // 2) # Write the new bounding box in the original format f_out.write(f"{x_tl},{y_tl},{x_br},{y_br}\n")
This approach is faster and uses less memory since you're not holding all bounding boxes in a dictionary at once.
内容的提问来源于stack exchange,提问作者Sulphur

