說明 1:dict.pop() 的兩件事
- 從字典刪除指定 key
- 回傳該 key 對應的 value(這個回傳值就是我們要「搬家」再插入用的值)
執行這格觀察效果:
data = {'a': 1, 'b': 2}
val = data.pop('a') # 刪除 'a',同時拿到它的 value
print('pop 回傳的值:', val)
print('pop 後的字典:', data)
# 把剛剛拿到的值再插回去
data['a'] = val
print('重新插入後的字典(a 會在最後):', data)
輸出結果:
說明 2:準備一個相像但簡化的字典
- 目標:把「鍵名包含 向量 / vector / embedding」的項目移到字典最後
- 只看「鍵名」,不看「值」內容
- 像 basename 這種重要鍵名不含關鍵字,即使值裡有 vector 也不移動
data = {
'basename': 'fixtureRepair_nl_vector_info.json',
# 重要資訊,鍵名不含向量關鍵字 -> 不移
'index': 0,
'向量(by gpt-4.1)': [0.12, -0.03, 0.8], # 需要被移到最後
'向量(by f-string)': [0.02, 0.03, 0.75], # 需要被移到最後
'desc': '值裡面可能有 vector,但我們不看值',
'vector_norm': 0.98, # 需要被移到最後
'meta': {'source': 'x'}
}
print('原始順序:')
data
輸出:
說明 3:設定關鍵字(大小寫不敏感)
keywords = ['向量', 'vector', 'embedding']
kw_lower = [k.lower() for k in keywords]
kw_lower
輸出:
說明 4:為何不要一邊遍歷一邊改字典?
- 遍歷同時改動結構,容易跳鍵或出錯
- 作法:先收集要移動的鍵,再統一處理
to_move = []
for k in list(data.keys()): # 用 list(...) 先拍下當前鍵的快照
if isinstance(k, str): # 僅處理字串鍵
kl = k.lower()
if any(sub in kl for sub in kw_lower):
to_move.append(k)
print('待移動的鍵:', to_move)
輸出:
說明 5:用 pop 拿出值,再插回末尾(達成「搬到最後」)
for k in to_move:
v = data.pop(k) # 1) 刪除該鍵並拿到 value
data[k] = v # 2) 重新插入 -> 會出現在字典末尾
print('搬移後的順序:')
data
輸出:
說明 6:觀念總結
- pop 同時「刪除鍵並回傳值」,這個回傳值就是我們能「先拿出再插回」的關鍵
- Python 3.7+ 的 dict 會保留插入順序,因此重新插入即代表「移到最後」
- 先收集鍵再統一 pop/插入,避免邊遍歷邊修改
- 只看鍵名是否含關鍵字,值中即使有關鍵字也不影響(例如 basename 的值含 vector 仍不會被移動)
- 想要精準匹配就縮小關鍵字清單;想要寬鬆匹配就擴大清單或改用正則
推薦hahow線上學習python: https://igrape.net/30afN
封裝為函數:
# %%
from typing import Iterable
def move_keys_to_end(d: dict,
key_words: Iterable[str] = ('向量', 'vector', 'embedding'),
case_sensitive: bool = False):
"""
在「當前字典」層級,把鍵名包含任一關鍵字的項目移到字典最後。
- d: 就地修改的字典
- key_words: 關鍵字清單
- case_sensitive: 是否大小寫敏感;預設 False(不敏感)
回傳:同一個 d(已就地修改)
"""
if not isinstance(d, dict):
raise TypeError("d 必須是 dict")
# 預處理大小寫
if case_sensitive:
# 大小寫敏感:如實比較
to_move = [k for k in list(d.keys())
if isinstance(k, str) and any(kw in k for kw in key_words)]
else:
# 大小寫不敏感:全部轉小寫再比
kw_lower = tuple(str(kw).lower() for kw in key_words)
to_move = []
for k in list(d.keys()):
if isinstance(k, str):
k_lower = k.lower()
if any(kw in k_lower for kw in kw_lower):
to_move.append(k)
# 依序 pop 再插回末尾
for k in to_move:
v = d.pop(k)
d[k] = v
return d
# 測試(單層)
data = {
'basename': 'fixtureRepair-2025-03-21_nl_vector_info.json',
'向量_Info': [0.1, 0.2],
'Vector_Norm': 0.98,
'embedding_used': True,
'index': 0
}
print('原本順序:', list(data.keys()))
move_keys_to_end(data, key_words=('向量', 'vector', 'embedding'), case_sensitive=False)
print('大小寫不敏感後:', list(data.keys()))
# 再來一份以測大小寫敏感
data2 = {
'basename': 'x',
'向量_Info': [0.1, 0.2],
'Vector_Norm': 0.98, # 注意 V 是大寫
'vector_norm': 0.97, # 小寫
'index': 0
}
print('原本順序2:', list(data2.keys()))
move_keys_to_end(data2, key_words=('vector',), case_sensitive=True) # 只匹配小寫 'vector'
print('大小寫敏感後(只移小寫 vector):', list(data2.keys()))
輸出:
多一個inplcae參數:
from typing import Iterable
from copy import deepcopy
def move_keys_to_end_safe(d: dict,
key_words: Iterable[str] = ('向量', 'vector', 'embedding'),
case_sensitive: bool = False,
in_place: bool = False):
"""
說明:
依鍵名包含關鍵字,把該項目移到字典最後。
參數:
d: 原始字典
key_words: 關鍵字
case_sensitive: 大小寫敏感與否
in_place: 是否就地修改。False 時會建立淺拷貝;True 則直接修改 d。
回傳:
修改後的字典(若 in_place=True,回傳的是 d 自身;否則是拷貝)
風險註記:
就地修改可能影響共用引用;請酌量使用。
"""
if not isinstance(d, dict):
raise TypeError("d 必須是 dict")
target = d if in_place else d.copy() # 淺拷貝;需要遞迴處理時請用 deepcopy
if case_sensitive:
to_move = [k for k in list(target.keys())
if isinstance(k, str) and any(kw in k for kw in key_words)]
else:
kw_lower = tuple(str(kw).lower() for kw in key_words)
to_move = []
for k in list(target.keys()):
if isinstance(k, str):
k_lower = k.lower()
if any(kw in k_lower for kw in kw_lower):
to_move.append(k)
for k in to_move:
v = target.pop(k)
target[k] = v
return target
# 示範:不就地修改(回傳新 dict)
orig = {'A': 1, 'vector_x': 2, 'b': 3}
new1 = move_keys_to_end_safe(orig, key_words=('vector',), case_sensitive=False, in_place=False)
print('orig:', orig)
print('new1:', new1)
# 示範:就地修改(orig 會被改)
orig2 = {'A': 1, 'vector_x': 2, 'b': 3}
new2 = move_keys_to_end_safe(orig2, key_words=('vector',), case_sensitive=False, in_place=True)
print('orig2(被改):', orig2)
print('new2(同一參考):', new2)
輸出:
推薦hahow線上學習python: https://igrape.net/30afN