web-dev-qa-db-fra.com

Mapper la liste dans le dictionnaire

Existe-t-il un moyen de mapper une liste sur un dictionnaire? Ce que je veux faire, c'est lui donner une fonction qui renverra le nom d'une clé, et la valeur sera la valeur d'origine. Par exemple;

somefunction(lambda a: a[0], ["hello", "world"])
=> {"h":"hello", "w":"world"}

(Ce n'est pas un exemple spécifique que je veux faire, je veux une fonction générique comme map() qui peut le faire)

27
Jeffrey Aylesworth

Je ne pense pas qu'il existe une fonction standard qui fasse exactement cela, mais il est très facile d'en construire une en utilisant le dict intégré et une compréhension:

def somefunction(keyFunction, values):
    return dict((keyFunction(v), v) for v in values)

print somefunction(lambda a: a[0], ["hello", "world"])

Production:

{'h': 'hello', 'w': 'world'}

Mais trouver un bon nom pour cette fonction est plus difficile que de l'implémenter. Je vais laisser cela comme un exercice pour le lecteur.

27
Mark Byers

Dans Python 3 vous pouvez utiliser cette syntaxe de compréhension de dictionnaire:

def foo(somelist):
    return {x[0]:x for x in somelist}
36
mkotechno

Si je comprends bien votre question, je pense que vous pouvez y parvenir avec une combinaison de map, Zip et du constructeur dict:

def dictMap(f, xs) :
    return dict(Zip(map(f, xs), xs)

Et une mise en œuvre plus saine:

def dictMap(f, xs) :
    return dict((f(i), i) for i in xs)
5
sykora

Si vous voulez qu'une fonction générale fasse cela, alors vous posez presque la bonne question. Cependant, votre exemple ne spécifie pas ce qui se passe lorsque la fonction clé produit des doublons. Gardez-vous le dernier? Le premier? Voulez-vous réellement faire une liste de tous les mots qui commencent par la même lettre? Il est préférable de répondre à ces questions par l'utilisateur de la fonction, et non par le concepteur.

Le paramétrage de ces résultats donne une fonction plus compliquée, mais très générale. En voici une que j'utilise depuis plusieurs années:

def reduce_list(key, update_value, default_value, l):
    """Reduce a list to a dict.

    key :: list_item -> dict_key
    update_value :: key * existing_value -> updated_value
    default_value :: initial value passed to update_value
    l :: The list 

    default_value comes before l. This is different from functools.reduce, 
    because functools.reduce's order is wrong.
    """
    d = {}
    for k in l:
        j = key(k)
        d[j] = update_value(k, d.get(j, default_value))
    return d

Ensuite, vous pouvez écrire votre fonction en disant:

reduce_list(lambda s:s, lambda s,old:s[0], '', ['hello', 'world'])
# OR
reduce_list(lambda s:s, lambda s,old: old or s[0], '', ['hello', 'world'])

Selon que vous souhaitez conserver le premier ou le dernier mot commençant par, par exemple, "h".

Cette fonction est cependant très générale, donc la plupart du temps elle sert de base à d'autres fonctions, comme group_dict ou histogram:

def group_dict(l):
    return reduce_list(lambda x:x, lambda x,old: [x] + old, [], l)
def histogram(l):
    return reduce_list(lambda x:x, lambda x,total: total + 1, 0, l)
1

En prenant des indices à partir d'autres réponses, j'ai réalisé cela en utilisant l'opération de carte. Je ne sais pas si cela répond exactement à votre question.

mylist = ["hello", "world"]
def convert_to_dict( somelist ):
    return dict( map( lambda x: (x[0], x), somelist ) )

final_ans = convert_to_dict( mylist ) 
print final_ans
1
Pulkit Bansal
>>> dict((a[0], a) for a in "hello world".split())
{'h': 'hello', 'w': 'world'}

Si vous souhaitez utiliser une fonction au lieu d'indexer, utilisez operator.itemgetter:

>>> from operator import itemgetter
>>> first = itemgetter(0)
>>> dict((first(x), x) for x in "hello world".split())
{'h': 'hello', 'w': 'world'}

Ou en fonction:

>>> dpair = lambda x : (first(x), x)
>>> dict(dpair(x) for x in "hello world".split())
{'h': 'hello', 'w': 'world'}

Enfin, si vous souhaitez plus d'un mot par lettre, utilisez collections.defaultdict

>>> from collections import defaultdict
>>> words = defaultdict(set)
>>> addword = lambda x : words[first(x)].add(x)
>>> for Word in "hello house home hum world wry wraught".split():
        addword(Word)


>>> print words['h']
set(['house', 'hello', 'hum', 'home'])
1
Ryan Ginstrom