Wie kann ich zwei Wörterbücher in Vim zusammenführen?

9

Ich habe zwei Diktate:

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

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

Wie kann ich die Schlüssel zusammenführen, overridedamit ich ein neues Diktat wie folgt erhalte:

{'hello': 'mars', 'bye': 'jupiter'}
Martin Tournoij
quelle

Antworten:

7

Sie können verwenden extend():

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

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

Schlüssel aus dem zweiten Argument überschreiben alle vorhandenen im ersten. Das defaultsDiktat wird an Ort und Stelle geändert , was möglicherweise nicht erwünscht ist. Verwenden Sie copy(), um dies zu verhindern:

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

Dies ist besonders dann zu beachten, wenn Sie ein Diktat an eine Funktion übergeben, da es als Referenz übergeben wird (sodass es auch außerhalb der Funktion geändert wird).


Beachten Sie, dass verschachtelte Dikte nicht zusammengeführt werden. Dies kann eine gute Sache sein oder auch nicht, je nachdem, wonach Sie suchen:

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

Sie benötigen eine kleine Hilfsfunktion, um verschachtelte Dicts rekursiv zusammenzuführen:

" 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

Sie können das entfernen, copy()wenn Sie es an Ort und Stelle ändern möchten (etwas schneller, aber möglicherweise unerwartet).

Martin Tournoij
quelle