2011-06-15 4 views
4

Quand jeessayer de comprendre lambda

dict = {'Alice': '7898', 'Beth': '9102', 'Cecil': '3258'} 
print filter(lambda x: x, dict['Alice']) 

il montre: 7898

Quand je fais la prochaine

dict = {'Alice': '2341', 'Beth': '9102', 'Cecil': '3258'} 
print filter(lambda x: x=="2341", dict['Alice']) 

il montre:

Pourquoi il ne montre pas Vrai. Comment devenir vrai?

+1

vous devez utiliser la liste compréhensions au lieu de 'filter' et' map' –

+3

Ne pas utiliser 'dict' comme nom de variable. C'est le nom du type de dictionnaire Python. –

Répondre

4

Il ressemble à votre malentendu est avec filter, pour moi. Vous passez une fonction de prédicat et un objet itérable à filter. Il crée un nouvel objet contenant les éléments du premier itérable pour lequel le prédicat renvoie une valeur vraie (pas nécessairement True lui-même, juste quelque chose qui teste comme vrai). L'itérable dans les deux cas est la chaîne '2341', ce qui signifie que les lettres individuelles sont testées. Bien sûr, la chaîne '2341' n'est pas égale à '2', '3', '4' ou '1'.

Essayez avec un tuple et il est plus facile de voir ce qui se passe:

>>> tup = tuple(dict['Alice']) 
>>> tup 
('7', '8', '9', '8') 
>>> filter(lambda x: x, tup) 
('7', '8', '9', '8') 
>>> tup 
('7', '8', '9', '8') 
>>> filter(lambda x: x, tup) 
('7', '8', '9', '8') 
>>> filter(lambda x: x=="2341", tup) 
() 
3

Voulez-vous tester si l'entrée 'Alice' est '2341'? Vous pouvez le faire via

print dict['Alice'] == '2341' 

Le problème que vous rencontrez est pas avec la forme de lambda, mais avec la méthode filter qui ne convient pas dans ce cas d'utilisation.

En général, une forme lambda est plus ou moins rien d'autre qu'une fonction anonyme (voir par exemple here).

1

Peut-être ce que vous essayez de faire est:

>>> dic = {'Alice': '2341', 'Beth': '9102', 'Cecil': '3258'} 
>>> [i for i in dic if dic[i] == '2341'] 
['Alice'] 

Et si vous ajoutez d'autres éléments avec la même valeur, vous obtiendrez tous puis dans la liste

5

filter() effectue les opérations suivantes: étant donné une fonction et un itérable (comme une liste, tuple, etc.), passe chaque élément la liste à une fonction. Pour chaque élément, la fonction renvoie un booléen vrai ou faux. Si la fonction renvoie true sur un élément, l'élément est ajouté à une nouvelle liste.

Lorsque le filtre est terminé, il renvoie la nouvelle liste avec tous les éléments sélectionnés. Cela vous permet de "filtrer" dans une liste en fonction d'un critère et de sélectionner uniquement les éléments correspondant aux critères.

Une chose délicate se passe ici. filter() boucle à travers tout itérable. Cela inclut une chaîne. Lorsque vous passez dict ['Alice'] en tant qu'objet à itérer, il passe '2341' et exécute le filtre sur chaque caractère de la chaîne. Vous pouvez briser la logique du filtre comme suit:

def matches(x): 
    return x == '2341' 

result = '' 
for char in x: 
    if matches(char): 
     result += char 

print result 

Cela ne fonctionne pas, car aucun de vos personnages individuels égaux « 2341 ».

0

Si vous voulez juste appeler la fonction lambda que vous utilisez juste comme une fonction:

print (lambda x: x=="2341")(dict["Alice"]) 

Cela donne le résultat attendu (vrai). Lorsque vous utilisez filter, il traite son second argument comme une liste, ainsi "2341" est traité comme une liste de caractères ['2', '3', '4', '1'], dont aucun n'est égal à "2341".

Chose intéressante, je viens de découvrir: Python 3 renvoie des objets de filtre de la fonction filter(), de sorte que l'utilisation correcte du filtre est

print(list(filter(lambda x: x, dict['Alice']))) 

Et que retours ['2', '3', '4', '1'] ce qui aurait évité la confusion initiale.

+0

Une différence étrange dans 2.X: 'filter' une chaîne et il renvoie une chaîne filtrée,' filter' une liste et il renvoie un _list_ filtré. Les listes de compréhension retournent toujours une liste. –

0

Normalement, on applique filter à deux arguments:

  1. fonction
  2. une liste (ou un autre objet iterable)

filter applique la fonction à chaque objet dans la liste et retourne une liste de tous les objets pour lesquels la fonction a retourné True.

Dans votre deuxième exemple, votre premier argument est une fonction, comme prévu. Mais votre deuxième argument n'est pas une liste — c'est une chaîne "2341" (le résultat de la recherche "Alice" dans le dictionnaire).

(Modifier: J'ai mal compris la partie suivante au début, merci à d'autres affiches pour bien faire les choses.) Filter traite la chaîne comme une liste, applique la fonction à chaque caractère et ne conserve que les caractères pour lesquels elle est retournée True (aucun d'entre eux), ce qui entraîne une chaîne vide. Maintenant, si vous regardez votre premier exemple, il a le même problème, et c'est seulement (mauvais?) De la chance que la réponse était ce que vous attendiez.

Comme un autre poster suggéré, peut-être vous voulez appliquer votre fonction plus directement. Dans le premier exemple:

(lambda x: x)(dict['Alice']) 

Dans le second exemple:

(lambda x: x=="2341")(dict['Alice'])