Quero escrever uma função em Julia que mescle dois dicionários.
function merge(left::Dict, right::Dict)::Dict
A semântica é a seguinte:
- As entradas são
left
eright
- Ambos
left
eright
assumiram a propriedade de seus dados, o que significa que eles serão modificados após a chamada da função e nenhuma garantia sobre os dados que eles contêm deve ser feita - O valor de retorno contém os dados de ambos os dicionários
- Se alguma chave estiver presente em ambos
left
eright
o valor deleft
for mantido
Aqui está uma ideia inicial sobre como abordar esse problema. (Este é um pseudocódigo com notas, não algo que realmente será compilado.)
function mergeDict(left::Dict, right::Dict)::Dict
# create a new dictionary from `left`
return_value = left
# move data from `right` to `left`, "no-clobber"
for k, v in pop_next!(right)
# the function `pop_next!` does not exist, no iterator-like `pop!`
for k in keys(right)
v = pop!(right, k)
# does this work as expected? destructive operation while reading keys?
# `keys()` returns an *iterator*, not a collection! (?)
if !haskey(left, k)
push!(left, k, v) # no `push!` function
left[k] = v # this works instead
end
end
# `left` and `right` are not pointers, but "copy-by-value references"
# just as in Python, so this doesn't work
left = nothing
right = nothing
# we want to invalidate the data, how to do that?
# this also won't work because `left` references the same data
# structure as `return_value`
clear(left)
clear(right)
end
Você pode ver que eu tentei escrever uma implementação manual. Tenho quase certeza de que Julia terá algumas funções úteis como parte da biblioteca padrão para implementar isso, no entanto, sendo novo em Julia, não sei o que elas podem ser.
Encontrei as funções merge
, mergewith
, merge!
e , mergewith!
no entanto nenhuma delas parece ter a semântica descrita acima.
As diferenças entre a função desejada e
merge
a que parece ser(1) em caso de conflitos, o dicionário mesclado deve conter o valor do
left
dicionário em vez do valor doright
dicionário, e(2) deve remover os pares transferidos dos dicionários de entrada.
Se a mesma chave aparecer em ambos os dicionários, então há uma decisão a ser tomada. Sua função poderia (a) remover os pares de ambos os dicionários, ou (b) remover apenas o par transferido do
left
dicionário.Para a parte 1, sua função pode chamar as funções Julia. Ou:
1a: Troque o primeiro e o segundo argumentos para
merge
, como emmerge(right, left)
. Ou1b: Forneça
mergewith
umacombine
função que selecione seu primeiro argumento, como emmergewith( (a,b)->a, left, right)
.Para a parte 2, sua função pode
2a. use
empty!
em ambas as entradas como emempty!(left)
eempty!(right)
(se as entradas ambas devem ficar vazias apesar dos conflitos). Ou2b. usar
empty!(left)
efilter!(pair -> pair.first in keys(left), right)
(manter chaves conflitantes emright
seright
pares não transferidos para o dicionário mesclado devem permanecer emright
)(Dica:
methodswith(Dict, supertypes=true)
lista assinaturas de métodos que aceitam umDict
, incluindoempty!
efilter!
.)Exemplo