Làm thế nào tôi có thể hợp nhất hai từ điển trong Vim?


9

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:


7

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.