Як я можу об'єднати два словники у Vim?


9

У мене два дикти:

: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'}

Клавіші з другого аргументу переосмислюють будь-які існуючі в першому. 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()якщо хочете змінити його на місці (трохи швидше, але, можливо, несподівано).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.