Je veux vérifier si un élément est déjà dans une liste avec égalité référentielle et non avec égalité structurelle.
Pour plus de clarté:
l'égalité référentielle entre 2 items est vérifiée avec
item1 est item2
L'égalité structurelle est vérifiée avec
item1 == item2
L'égalité structurelle pour vérifier si un élément est déjà dans une liste se fait facilement comme ceci:
def get_all_items_in_list(items): all_items = [] for item in items: if not item in all_items: # replace with referential equality here all_items.append(item) return all_items # setup a = (1, []) b = (1, []) print(a is b) # prints False items = [a, a, b] print(get_all_items_in_list(items)) # should print [(1, []), (1, [])] but prints [(1, [])]
Je cherche donc une ligne équivalente avec référentiel égalité. Est-ce possible sans boucler sur chaque élément de la liste?
Un exemple de la façon dont cela doit être implémenté (juste pour clarifier):
item in list
5 Réponses :
Essayez ceci,
a=10 b=20 c=30 l=[id(a),id(b),id(c)] id(a) in l
Je pense que cela fonctionnerait dans certains cas si vous avez une liste statique, mais dans mon application, les éléments sont ajoutés dynamiquement au tableau. Donc je ne peux pas faire ça comme ça.
Ainsi, selon "is" l'opérateur python , il vérifie le identité
des objets, qui peut être obtenue avec la fonction id ()
( faire défiler plus loin pour la solution ).
# another thing to notice is that a simple copy() # will return the same object from copy import copy e = (3, []) f = copy(e) print(e is f) print(id(e), id(f)) >>> True >>> 2076884710600 2076884710600 # but a deepcopy will change the identity from copy import deepcopy g = (4, []) h = deepcopy(g) print(g is h) print(id(g), id(h)) >>> False >>> 2076884714120 2076884715016SOLUTION:
L'idée ci-dessous est d'obtenir tous les identifiants () dans une autre liste avec la même position que la liste d'origine. Lorsque vous vérifiez si l'élément est dans la liste, vous vérifierez si l'identité est déjà dedans.
def get_ids_items_in_list(items): """ Get the identity of the objects in same order as list""" items_ids = [] for item in items: items_ids.append(id(item)) return items_ids def get_all_items_in_list(items_list): # get our ids items_ids = get_ids_items_in_list(items_list) all_items = [] all_items_id = [] # Loops over the ids but using enumerate to get positions for idx, item in enumerate(items_ids): if not item in all_items_id: all_items_id.append(item) # if id is in list, append object according to position all_items.append(items_list[idx]) return all_items # setup a = (1, []) b = (1, []) print(a is b) # prints False items = [a, a, b] print(get_all_items_in_list(items)) >>> False >>> [(1, []), (1, [])]
PLUS SUR LE SUJET:
# as you did a = (1, []) b = (1, []) # two different objects print(a is b) print(id(a), id(b)) >>> False >>> 2076884715144 2076884729224 # Now let's try making the second object the same c = (2, []) d = c #objects are the same print(c is d) print(id(c), id(d)) >>> True >>> 2076899815240 2076899815240
Vous pouvez utiliser un dict
intermédiaire saisi par l'élément id
comme ensemble d'identité:
def get_all_items_in_list(items): return {id(it): it for it in items}.values() # arrange a = (1, []) b = (1, []) items = [a, a, b] # act result = list(get_all_items_in_list(items)) # assert print(result[0] is a) print(result[1] is b)
Vous ne pourrez pas faire cela sans une sorte de boucle. Il n'y a pas d'opérateur équivalent en python de dans
qui vérifie l'identité. Une solution courte pourrait ressembler à ceci:
from collections import UserList class identList(UserList): def __contains__(self, other): return any(other is sub for sub in self) l = [1,2,3] l2 = identList([[1, 2, 3], [4, 5, 6]]) l3 = identList([[1, 2, 3], [4, 5, 6], l]) l in l2 # False l in l3 # True
Elle boucle toujours, mais elle se terminera tôt si une vraie valeur est trouvée.
Si vous vraiment em> nécessaire pour utiliser un opérateur pour cela, vous pouvez sous-classer UserList
et remplacer __contains __ ()
. Cela changerait le comportement de in
:
l = [1,2,3] l2 = [[1, 2, 3], [4, 5, 6]] l3 = [[1, 2, 3], [4, 5, 6], l] any(l is sub for sub in l2) # false any(l is sub for sub in l3) # True
False dict_values([(1, []), (1, [])])
Cette question est une copie de Vérifier si l'objet est dans la liste (pas «par valeur», mais par identifiant) . Je ne peux pas voter pour le fermer actuellement en raison de la prime ouverte.