1
votes

Vérifier si l'élément est déjà dans une liste avec l'égalité référentielle

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


1 commentaires

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.


5 Réponses :


0
votes

Essayez ceci,

a=10
b=20
c=30
l=[id(a),id(b),id(c)]
id(a) in l


1 commentaires

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.



1
votes

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 2076884715016
SOLUTION:

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


0 commentaires

1
votes

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)


0 commentaires

3
votes

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


0 commentaires

1
votes
False

dict_values([(1, []), (1, [])])

0 commentaires