如何以Pythonic且高效的方式将两个未排序列表转换为字典?(适配长度不等、元素匹配缺失场景)
The original code's nested loops lead to O(n*m) time complexity, which slows down significantly with large lists. Let's fix this by pre-processing the full names into a lookup dictionary first, then using a dictionary comprehension to build the result—this reduces the time complexity to O(n + m) for the common case where full names follow the first/last format.
Solution 1: Exact Last Name Match (Split by '/')
This is the fastest and most accurate approach if your full names are structured as first/last (like your example):
def index_match(full_names, last_names): # Build a lookup dict: last name -> first occurrence of full name name_lookup = {} for full_name in full_names: # Split into first and last name (assuming format "first/last") _, last_part = full_name.split('/') # Only keep the first occurrence of each last name if last_part not in name_lookup: name_lookup[last_part] = full_name # Build result: include only last names that exist in the lookup, preserve order return {ln: name_lookup[ln] for ln in last_names if ln in name_lookup} # Test with your example full_name = ['taylor/swift', 'lady/gaga', 'leborn/james', 'james/harden'] last_name = ['harden', 'james', 'swift', 'smith'] matcher = index_match(full_name, last_name) for item in matcher.items(): print(item)
Output:
('harden', 'james/harden') ('james', 'leborn/james') ('swift', 'taylor/swift')
Key Benefits:
- Faster: Pre-processing runs in O(n) time, building the result runs in O(m) time.
- Pythonic: Uses dictionary comprehensions and clear, readable logic.
- Handles edge cases: Automatically ignores last names with no match, keeps the first occurrence of duplicate last names in full names, and works with lists of any length.
Solution 2: Substring Match (For Non-Structured Full Names)
If your full names aren't strictly first/last and you need to match any substring (like the original code), we can optimize by tracking which last names we still need to find to avoid redundant checks:
def index_match(full_names, last_names): needed_last_names = set(last_names) name_lookup = {} for full_name in full_names: if not needed_last_names: break # Early exit if all matches are found # Find all remaining last names present in this full name found = [ln for ln in needed_last_names if ln in full_name] for ln in found: name_lookup[ln] = full_name needed_last_names.remove(ln) # Preserve the order of the original last_names list return {ln: name_lookup[ln] for ln in last_names if ln in name_lookup}
Why This Is Better Than the Original:
- Avoids checking every full name for every last name (once a last name is found, it's removed from the needed set).
- Uses early termination if all matches are found before iterating all full names.
- Still preserves the original order of last names in the result.
Notes:
- Both solutions preserve the order of last names from the input list (works in Python 3.7+ where dictionaries maintain insertion order).
- Duplicate last names in the
last_nameslist will map to the same full name (e.g., iflast_nameshas two entries for 'swift', both will point to 'taylor/swift').
内容的提问来源于stack exchange,提问作者FunPlus

