2009-08-20 13 views
141

Testé sur interpréteur Python 2.6:Python: Ajouter une liste à définir?

>>> a=set('abcde') 
>>> a 
set(['a', 'c', 'b', 'e', 'd']) 
>>> l=['f','g'] 
>>> l 
['f', 'g'] 
>>> a.add(l) 
Traceback (most recent call last): 
    File "<pyshell#35>", line 1, in <module> 
    a.add(l) 
TypeError: list objects are unhashable 

Je pense que je ne peux pas ajouter la liste à l'ensemble parce qu'il n'y a aucun moyen Python peut dire si je l'ai ajouté la même liste deux fois. Y at-il un travail autour?

EDIT: Je veux ajouter la liste elle-même, pas ses éléments.

+2

Voulez-vous ajouter la liste à l'ensemble ou les éléments de la liste? – pkit

+0

La liste elle-même - Je veux avoir un ensemble de listes. –

+0

Ensuite, utilisez l'option de tuple à laquelle Otto a répondu. – pkit

Répondre

131

Vous ne pouvez pas ajouter de liste à un ensemble car les listes sont modifiables, ce qui signifie que vous pouvez modifier le contenu de la liste après l'avoir ajouté à l'ensemble.

Vous pouvez cependant ajouter tuples à l'ensemble, parce que vous ne pouvez pas modifier le contenu d'un tuple:

>>> a.add(('f', 'g')) 
>>> print a 
set(['a', 'c', 'b', 'e', 'd', ('f', 'g')]) 

Modifier: quelques explications: La documentation définit un set comme une collection non ordonnée d'objets lavables distincts. Les objets doivent être modifiables de sorte que la recherche, l'ajout et la suppression d'éléments puissent être effectués plus rapidement que l'examen de chaque élément individuel chaque fois que vous effectuez ces opérations. Les algorithmes spécifiques utilisés sont expliqués dans le Wikipedia article. Pythons algorithmes de hachage sont expliqués sur effbot.org et pythons __hash__ fonction dans le python reference.

Quelques faits:

  • Set éléments ainsi que clés de dictionnaire doivent être hashable
  • Certains unhashable types de données:
    • list: utiliser tuple à la place
    • set: utiliser frozenset au lieu de
    • dict: n'a pas d'équivalent officiel, mais il y a des recipes
  • instances d'objets sont indexables par défaut avec chaque instance ayant un hachage unique. Vous pouvez remplacer ce comportement comme expliqué dans la référence python.
+4

Et si vous voulez ajouter un ensemble à un ensemble, utilisez frozenset. – FogleBird

+4

['collections.namedtuple'] (http://docs.python.org/library/collections.html#collections.namedtuple) peut être considéré comme une contrepartie" officielle "du' dict'. – SilentGhost

+2

@FogleBird ou l'opérateur de l'union: | = – aehlke

332
>>> a = set('abcde') 
>>> l = ['f', 'g'] 
>>> a |= set(l) 
>>> a 
set(['a', 'c', 'b', 'e', 'd', 'g', 'f']) 

L'opérateur syndical est beaucoup plus rapide que d'ajouter de toute façon.

Modifier: Si vous voulez la liste elle-même et non ses membres, alors vous devez utiliser un tuple, malheureusement. Les membres de l'ensemble doivent être lavables.

+20

'a.update (l)' a le même effet. –

8

les objets de la liste sont indisponibles. vous pourriez vouloir les transformer en tuples cependant.

3

Vous voudrez utiliser des tuples, qui sont hashable (vous ne pouvez pas hacher un objet mutable comme une liste).

>>> a = set("abcde") 
>>> a 
set(['a', 'c', 'b', 'e', 'd']) 
>>> t = ('f', 'g') 
>>> a.add(t) 
>>> a 
set(['a', 'c', 'b', 'e', 'd', ('f', 'g')]) 
+0

Wow, nous avons écrit presque exactement la même chose en même temps. – hughdbrown

4

Vous voulez ajouter un tuple, pas une liste:

>>> a=set('abcde') 
>>> a 
set(['a', 'c', 'b', 'e', 'd']) 
>>> l=['f','g'] 
>>> l 
['f', 'g'] 
>>> t = tuple(l) 
>>> t 
('f', 'g') 
>>> a.add(t) 
>>> a 
set(['a', 'c', 'b', 'e', 'd', ('f', 'g')]) 

Si vous avez une liste, vous pouvez convertir au tuple, comme indiqué ci-dessus. Un tuple est immuable, donc il peut être ajouté à l'ensemble.

+0

vous n'avez pas besoin de tuple (x pour x en l) ', vous pouvez simplement faire:' tuple (l) ' – SilentGhost

+0

Ah, c'est vrai. J'ai une syntaxe de compréhension de liste coincée dans mes doigts. – hughdbrown

4

Les ensembles ne peuvent pas contenir d'éléments/éléments mutables (modifiables). Une liste, étant mutable, ne peut pas être membre d'un ensemble.

Comme les ensembles sont mutables, vous ne pouvez pas avoir un ensemble d'ensembles! Vous pouvez avoir un ensemble de frozensets cependant.

(Le même genre de « exigence de mutabilité » applique aux touches d'un dict.)

D'autres réponses ont déjà donné le code, j'espère que cela donne un peu de perspicacité. J'espère que Alex Martelli répondra avec encore plus de détails.

2

J'ai trouvé que j'avais besoin de faire quelque chose de similaire aujourd'hui. L'algorithme savait quand il créait une nouvelle liste qui devait être ajoutée à l'ensemble, mais pas quand il aurait fini de fonctionner sur la liste.

De toute façon, le comportement que je voulais était d'utiliser id plutôt que hash. En tant que tel, j'ai trouvé mydict[id(mylist)] = mylist au lieu de myset.add(mylist) pour offrir le comportement que je voulais.

13

Veuillez noter la fonction set.update(). La documentation dit:

Mettre à jour un ensemble avec l'union de lui-même et d'autres.

+5

Cela ne répond pas à la question (puisque l'OP veut ajouter la liste elle-même à l'ensemble) mais c'était la réponse dont j'avais besoin quand Google m'a amené ici :-) –

+1

Eh bien, il semble que la réponse la plus pertinente à question à moi ... par exemple, si b = set ([1]), b.update ([7,25]) donnera à b la valeur suivante: set ([1, 25, 7]) ---> N'est-ce pas ce que nous cherchons ici? –

37

Espérons que cela aide:

>>> seta = set('1234') 
>>> listb = ['a','b','c'] 
>>> seta.union(listb) 
set(['a', 'c', 'b', '1', '3', '2', '4']) 
>>> seta 
set(['1', '3', '2', '4']) 
>>> seta = seta.union(listb) 
>>> seta 
set(['a', 'c', 'b', '1', '3', '2', '4']) 
3

Voici comment je le fais habituellement il:

def add_list_to_set(my_list, my_set): 
    [my_set.add(each) for each in my_list] 
return my_set 
25

Pour ajouter les éléments d'une liste à un ensemble, utilisez update

Depuis https://docs.python.org/2/library/sets.html

s.update (t): return ensemble s avec des éléments ajoutés à partir de t

Par ex

>>> s = set([1, 2]) 
>>> l = [3, 4] 
>>> s.update(l) 
>>> s 
{1, 2, 3, 4} 

Si vous voulez plutôt ajouter la liste entière comme un seul élément à l'ensemble, vous ne pouvez pas parce que les listes ne sont pas indexables. Vous pourriez plutôt ajouter un tuple, par ex. s.add(tuple(l)). Voir aussi TypeError: unhashable type: 'list' when using built-in set function pour plus d'informations à ce sujet.

-1

Cela devrait faire:

set(tuple(i) for i in L) 
Questions connexes