Dado um dicionário, { k1: v1, k2: v2 ... }
eu quero obter { k1: f(v1), k2: f(v2) ... }
desde que eu passe uma função f
.
Existe alguma função incorporada? Ou eu tenho que fazer
dict([(k, f(v)) for (k, v) in my_dictionary.iteritems()])
Idealmente, eu apenas escreveria
my_dictionary.map_values(f)
ou
my_dictionary.mutate_values_with(f)
Ou seja, não me interessa se o dicionário original está mutado ou se uma cópia é criada.
python
dictionary
map-function
Tarrasch
fonte
fonte
dict((k, f(v)) for k, v in mydict.iteritems())
, ou seja, sem colchetes, que impediria a criação de uma lista intermediária por meio de um gerador.Respostas:
Não existe essa função; a maneira mais fácil de fazer isso é usar uma compreensão de ditado:
No python 2.7, use o
.iteritems()
método em vez de.items()
economizar memória. A sintaxe de compreensão de ditados não foi introduzida até o python 2.7.Observe que também não existe esse método nas listas; você precisaria usar uma compreensão de lista ou a
map()
função.Como tal, você também pode usar a
map()
função para processar seu dict:mas isso não é legível, na verdade.
fonte
dict(zip(a, map(f, a.values())))
é marginalmente mais curto, mas tenho que pensar no que está fazendo e me lembrar que sim, chaves e valores são iterados na mesma ordem, se o ditado não mudar. Não preciso pensar no que o dictcomp está fazendo, e por isso é a resposta certa.my_dictionary.__getitem__
.lambda (k,v): (k, f(v))
deve ser reescrito para algo comolambda k_v: (k_v[0], f(k_v[1]))
Essas ferramentas são ótimas para esse tipo de lógica simples, mas repetitiva.
http://toolz.readthedocs.org/en/latest/api.html#toolz.dicttoolz.valmap
Leva você exatamente onde você quer estar.
fonte
Você pode fazer isso no local, em vez de criar um novo ditado, que pode ser preferível para dicionários grandes (se você não precisar de uma cópia).
resulta em
my_dictionary
conter:fonte
mapdict
amutate_values_with
ou algo para deixar bem claro que você reescrever o dict! :)zip(d.keys(), d.values())
obras para mais versões em vez deiteritems()
{k:f(v) for k,v in iter(d.items())}
Devido ao PEP-0469, que renomeou iteritems () para items (), e PEP-3113, que removeu a descompactação do parâmetro Tuple , no Python 3.x, você deve escrever Martijn Pieters .
fonte
Embora minha resposta original tenha falhado o ponto (tentando resolver esse problema com a solução para acessar a chave na fábrica do padrão ), eu a refiz para propor uma solução real para a presente pergunta.
Aqui está:
Uso:
A idéia é subclassificar o ditado original para fornecer a funcionalidade desejada: "mapear" uma função sobre todos os valores.
O ponto positivo é que esse dicionário pode ser usado para armazenar os dados originais como se fossem
dict
, enquanto transforma qualquer dado sob solicitação com um retorno de chamada.Obviamente, sinta-se à vontade para nomear a classe e a função da maneira que desejar (o nome escolhido nesta resposta é inspirado na
array_walk()
função do PHP ).Nota: Nem o bloco
try
-except
nem asreturn
instruções são obrigatórias para a funcionalidade, elas existem para imitar ainda mais o comportamento do PHParray_walk
.fonte
__missing__
método não será chamado para chaves existentes, que queremos transformar, a menos que o método de fábrica passado use o dict de origem como um fallback de alguma forma, mas como isso não faz parte do exemplo de uso, Considero isso uma resposta insatisfatória para o problema em questão.Given a dictionary { k1: v1, k2: v2 ... } ...
. Ou seja, você já temdict
que começar com .. #{v1: f(v1), v2: f(v2), ...}
dados[v1, v2, ...]
, e não dados. Vou editar minha resposta para corrigir isso.Para evitar a indexação de dentro do lambda, como:
Você também pode fazer:
fonte
lambda(k,v)
, não funcionará. Veja stackoverflow.com/questions/21892989/…Apenas veio através deste caso de uso. Eu implementei a resposta de gens , adicionando uma abordagem recursiva para lidar com valores que também são ditados:
Isso pode ser útil ao lidar com arquivos json ou yaml que codificam cadeias de caracteres como bytes no Python 2
fonte