如何基于多键(pid/sid/eid)合并字典列表?
I totally get your frustration—most examples out there only cover merging on a single key, which doesn't help when you need to match on multiple fields like pid, sid, and eid. Let's walk through how to solve this properly for your specific case.
First, let's restate your input data for clarity:
x = [ {'pid':111, 'sid':6, 'eid':123, 'x_qty':30}, {'pid':222, 'sid':56, 'eid':6212, 'x_qty':2} ] y = [ {'pid':111, 'sid':6, 'eid':123, 'y_qty':123}, {'pid':333, 'sid':56, 'eid':6212, 'y_qty':112} ]
The core idea here is to use a temporary dictionary where the key is a tuple of the three matching fields (pid, sid, eid), and the value is the merged dictionary. We'll iterate through both lists, updating the temporary dict with entries from each list, then extract the values as our final result.
Here's a clean, efficient implementation:
# Initialize a temporary dictionary to hold merged entries merged_dict = {} # Process all entries from list x for item in x: # Create a unique key from the three matching fields key = (item['pid'], item['sid'], item['eid']) # Add the item to the temp dict (creates a new entry if key doesn't exist) merged_dict[key] = item.copy() # Use copy to avoid modifying original items # Process all entries from list y for item in y: key = (item['pid'], item['sid'], item['eid']) if key in merged_dict: # If key exists, merge the current item into the existing entry merged_dict[key].update(item) else: # If key doesn't exist, add it to the temp dict merged_dict[key] = item.copy() # Extract the values from the temp dict to get our final list z z = list(merged_dict.values())
If you print z, you'll get exactly the result you're expecting:
[ {'pid': 111, 'sid': 6, 'eid': 123, 'x_qty': 30, 'y_qty': 123}, {'pid': 222, 'sid': 56, 'eid': 6212, 'x_qty': 2}, {'pid': 333, 'sid': 56, 'eid': 6212, 'y_qty': 112} ]
Key Details to Note:
- Tuple as Key: Using
(pid, sid, eid)as the key works because tuples are hashable (unlike lists) and perfectly represent the unique combination of fields we need to match on. - Copying Items: We use
item.copy()to prevent unintended modifications to the original dictionaries in listsxandy. - Update Logic: When an entry from
ymatches an existing key inmerged_dict,update()merges the two dictionaries—this preserves all keys from both entries, with values fromyoverwritingxif there's a key conflict (though in your case, the keys are unique except for the matching fields, so this isn't an issue).
If you need to merge more than two lists later, you can easily wrap this in a reusable function:
def merge_on_multiple_keys(dict_lists, keys): merged = {} for lst in dict_lists: for item in lst: key = tuple(item[k] for k in keys) if key in merged: merged[key].update(item) else: merged[key] = item.copy() return list(merged.values()) # Usage example for your case: z = merge_on_multiple_keys([x, y], ['pid', 'sid', 'eid'])
内容的提问来源于stack exchange,提问作者Jason TK

