Ajouter une liste à définir?

242

Testé sur l'interpréteur Python 2.6:

>>> 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 car il n'y a aucun moyen pour Python de savoir si j'ai ajouté deux fois la même liste. Y at-il un travail autour?

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

Adam Matan
la source
2
Voulez-vous ajouter la liste à l'ensemble ou aux éléments de la liste?
pkit
La liste elle-même - je veux avoir un ensemble de listes.
Adam Matan
Il semble que la réponse la mieux adaptée soit la réponse sous-estimée, suggérant d'utiliser aSet.add (id (lst)) avant d'ajouter lst lui-même à une liste / file d'attente / etc, pour être sûr que vous l'avez fait vous-même. Vous devez reconsidérer la réponse acceptée.
Rustam A.

Réponses:

187

Vous ne pouvez pas ajouter une 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ée à l'ensemble.

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

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

Edit : quelques explications: La documentation définit un setcomme une collection non ordonnée d'objets lavables distincts. Les objets doivent être lavables afin que la recherche, l'ajout et la suppression d'éléments puissent être effectués plus rapidement que la consultation de chaque élément individuel à chaque fois que vous effectuez ces opérations. Les algorithmes spécifiques utilisés sont expliqués dans l'article Wikipedia . Les algorithmes de hachage Pythons sont expliqués sur effbot.org et la __hash__fonction pythons dans la référence python .

Quelques faits:

  • Les éléments de set ainsi que les clés de dictionnaire doivent être lavables
  • Quelques types de données non partageables:
    • list: utiliser à la tupleplace
    • set: utiliser à la frozensetplace
    • dict: n'a pas d'homologue officiel, mais il existe des recettes
  • Les instances d'objets sont hachables par défaut, chaque instance ayant un hachage unique. Vous pouvez remplacer ce comportement comme expliqué dans la référence python.
Otto Allmendinger
la source
6
Et si jamais vous voulez ajouter un ensemble à un ensemble, utilisez frozenset.
FogleBird
4
collections.namedtuplepourrait être considéré comme une contrepartie "officielle" de la dict.
SilentGhost
1
@Wahnfrieden: c'est ajouter le contenu d'un ensemble, pas l'ensemble lui-même.
Otto Allmendinger
@aehlke: Non, cela ajoute les éléments de l'ensemble au premier ensemble, mais nous parlons d'ajouter un ensemble comme élément du premier ensemble.
Jeff Learman
578

Utilisez set.update()ou|=

>>> a = set('abc')
>>> l = ['d', 'e']
>>> a.update(l)
>>> a
{'e', 'b', 'c', 'd', 'a'}

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

modifier: Si vous souhaitez ajouter la liste elle-même et non ses membres, vous devez malheureusement utiliser un tuple. Les membres du set doivent être lavables .

aehlke
la source
set.update () ajoute la liste à l'ensemble, correct? A quoi sert l'opérateur Pipe Equals?
FistOfFury
En ce qui concerne les ensembles, l' |opérateur implémente l' opération d'union d'ensemble . L' |=opérateur et la set.update()méthode appliquent cette opération sur place et sont effectivement synonymes. Donc, set_a |= set_bpourrait être considéré comme du sucre syntaxique pour les deux set_a.update(set_b) et set_a = set_a | set_b (sauf que dans ce dernier cas, le même set_aobjet est réutilisé plutôt que réaffecté). </ahem>
Cecil Curry
76

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

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

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

Par exemple

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

Si vous souhaitez plutôt ajouter la liste entière en tant qu'élément unique à l'ensemble, vous ne pouvez pas car les listes ne sont pas hachables. Vous pouvez à la place ajouter un tuple, par exemple s.add(tuple(l)). Voir aussi TypeError: unhashable type: 'list' lors de l'utilisation de la fonction set intégrée pour plus d'informations à ce sujet.

JDiMatteo
la source
40

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'])
alvas
la source
15

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

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

oeuf
la source
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 lorsque Google m'a amené ici :-)
tom stratton
1
Eh bien, cela me semble être la réponse la plus pertinente à la question ... 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 recherchons ici?
Louis LC
8

les objets de liste ne sont pas partageables . vous voudrez peut-être les transformer en tuples.

SilentGhost
la source
5

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

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

(Le même type de "condition de mutabilité" s'applique aux clés d'un dict.)

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

user135331
la source
4

Vous souhaitez 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 en tuple, comme indiqué ci-dessus. Un tuple est immuable, il peut donc être ajouté à l'ensemble.

Hughdbrown
la source
4

J'ai trouvé que je devais 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 d'opérer sur la liste.

Quoi qu'il en soit, le comportement que je voulais était idplutôt que d'utiliser hash. En tant que tel, j'ai trouvé mydict[id(mylist)] = mylistau lieu d' myset.add(mylist)offrir le comportement que je voulais.

Dunes
la source
3

Vous voudrez utiliser des tuples, qui sont lavables (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')])
Noé
la source
2

Voici comment je le fais habituellement:

def add_list_to_set(my_list, my_set):
    [my_set.add(each) for each in my_list]
return my_set
kashif
la source
-4

Cela devrait faire:

set(tuple(i) for i in L)
WQS
la source