web-dev-qa-db-fra.com

Python: Ajouter une liste à définir?

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 que Python puisse dire si j'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.

195
Adam Matan

Vous ne pouvez pas ajouter de liste à un ensemble car les listes sont mutables, 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 nuplets à 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 une set comme ne collection non ordonnée d'objets distincts pouvant être séparés. Les objets doivent être accessibles pour que la recherche, l’ajout et la suppression d’éléments soient plus rapides que l’examen de chaque élément à chaque fois que vous effectuez ces opérations. Les algorithmes spécifiques utilisés sont expliqués dans le article Wikipedia . Les algorithmes de hachage Pythons sont expliqués dans la fonction effbot.org et les pythons __hash__ dans référence python .

Quelques faits:

  • Les éléments de jeu ainsi que les clés de dictionnaire doivent être de type obligatoire.
  • Quelques types de données indispensables:
    • list: utilisez Tuple à la place
    • set: utilisez frozenset à la place
    • dict: n'a pas d'équivalent officiel, mais il en existe recettes
  • Les instances d'objet sont hasachables par défaut, chaque instance ayant un hachage unique. Vous pouvez remplacer ce comportement comme expliqué dans la référence python.
163
Otto Allmendinger

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'}

edit: Si vous souhaitez ajouter la liste elle-même et non ses membres, vous devez utiliser un tuple, malheureusement. Les membres de l'ensemble doivent être hashable .

454
aehlke

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

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

s.update (t): retourne un 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 hashable. Vous pouvez plutôt ajouter un tuple, par exemple s.add(Tuple(l)). Voir aussi TypeError: type inshashable: 'list' lors de l'utilisation de la fonction set intégrée pour plus d'informations à ce sujet.

67
JDiMatteo

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'])
39
alvas

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

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

14
eggfly

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

8
SilentGhost

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

Comme les ensembles sont modifiables, vous ne pouvez pas en avoir! Vous pouvez avoir un ensemble de frozensets cependant.

(Le même type "d'exigence 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 vous donne un aperçu. J'espère qu'Alex Martelli répondra avec plus de détails.

5
user135331

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

4
hughdbrown

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 de fonctionner sur la liste.

Quoi qu'il en soit, le comportement que je souhaitais était que l'ensemble utilise 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 souhaité.

3
Dunes

Vous voudrez utiliser des n-uplets, qui sont obligatoires (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')])
3
Noah

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
2
kashif