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 defaults
dict 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ờ).