Tôi có hai dicts:
:let defaults = {'hello': 'world', 'bye': 'jupiter'}
:let override = {'hello': 'mars'}
Làm cách nào tôi có thể hợp nhất các khóa từ overrideđó để kết thúc bằng một lệnh mới như vậy:
{'hello': 'mars', 'bye': 'jupiter'}
Tôi có hai dicts:
:let defaults = {'hello': 'world', 'bye': 'jupiter'}
:let override = {'hello': 'mars'}
Làm cách nào tôi có thể hợp nhất các khóa từ overrideđó để kết thúc bằng một lệnh mới như vậy:
{'hello': 'mars', 'bye': 'jupiter'}
Câu trả lời:
Bạn có thể sử dụng extend():
:let defaults = {'hello': 'world', 'bye': 'jupiter'}
:let override = {'hello': 'mars'}
:echo extend(defaults, override)
{'hello': 'mars', 'bye': 'jupiter'}
Các khóa từ đối số thứ hai ghi đè lên bất kỳ đối số hiện có nào trong đối số thứ nhất. Các defaultsdict sẽ được sửa đổi tại chỗ , mà có thể không được mong muốn. Sử dụng copy()để ngăn chặn điều đó:
:call extend(copy(defaults), override)
:echo defaults
{'hello': 'world', 'bye': 'jupiter'}
Điều này đặc biệt cần lưu ý khi bạn chuyển một lệnh cho hàm, vì nó được truyền bằng tham chiếu (vì vậy nó cũng sẽ được sửa đổi bên ngoài hàm).
Lưu ý rằng nó sẽ không hợp nhất các ký tự lồng nhau, có thể hoặc không phải là một điều tốt, tùy thuộc vào những gì bạn đang tìm kiếm:
:echo extend({'nest': {'a': 'b'}}, {'nest': {'b': 'XXXX'}})
{'nest': {'b': 'XXXX'}}
Bạn sẽ cần một hàm trợ giúp nhỏ để hợp nhất đệ quy các hàm lồng nhau:
" Merge two dictionaries, also recursively merging nested keys.
"
" Use extend() if you don't need to merge nested keys.
fun! s:merge(defaults, override) abort
let l:new = copy(a:defaults)
for [l:k, l:v] in items(a:override)
let l:new[l:k] = (type(l:v) is v:t_dict && type(get(l:new, l:k)) is v:t_dict)
\ ? s:merge(l:new[l:k], l:v)
\ : l:v
endfor
return l:new
endfun
Bạn có thể xóa copy()nếu bạn muốn sửa đổi tại chỗ (nhanh hơn một chút, nhưng có thể bất ngờ).