Vimで2つの辞書をマージするにはどうすればよいですか?


9

私は2つの口述を持っています:

:let defaults = {'hello': 'world', 'bye': 'jupiter'}

:let override = {'hello': 'mars'}

どのようにしてキーをマージして、override最終的に次のような新しい辞書を作成できますか?

{'hello': 'mars', 'bye': 'jupiter'}

回答:


7

使用できますextend()

:let defaults = {'hello': 'world', 'bye': 'jupiter'}
:let override = {'hello': 'mars'}

:echo extend(defaults, override)
{'hello': 'mars', 'bye': 'jupiter'}

2番目の引数のキーは、最初の引数の既存のキーをオーバーライドします。defaults辞書をされる場所に変更したいと思ったことがないかもしれません。それcopy()を防ぐために使用します:

:call extend(copy(defaults), override)
:echo defaults
{'hello': 'world', 'bye': 'jupiter'}

これは、ディクショナリを関数に渡すときに特に注意が必要です。ディクショナリは参照で渡されるためです(そのため、関数の外側でも変更されます)。


ネストされた辞書をマージしないことに注意してください。これは、探しているものに応じて、適切な場合とそうでない場合があります。

:echo extend({'nest': {'a': 'b'}}, {'nest': {'b': 'XXXX'}})
{'nest': {'b': 'XXXX'}}

ネストされた辞書を再帰的にマージするには、小さなヘルパー関数が必要です。

" 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

copy()インプレースで変更する場合は、ビットを削除できます(少し高速ですが、予期しない可能性があります)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.