user1956609
user1956609

Reputation: 2202

Using .index() with duplicate values that have separate identifiers

In the code below, I create identifiers a and b that point to two separate lists with the same value, verified by their unique id values.

Then I insert both into a list, and try to find the index for b, but instead it finds the index for a.

In [21]: a = [3,2]

In [22]: b = [3,2]

In [23]: id(a)
Out[23]: 4368404136

In [24]: id(b)
Out[24]: 4368429352

In [25]: c = [[4,3], a, [5,7], b, [6,3]]

In [26]: c.index(a)
Out[26]: 1

In [27]: c.index(b)
Out[27]: 1

How can I return 3? A while loop would work but it seems like there should be a function for this.

i = 0
match = False
while (not match) and (i < len(c)):
    if id(c[i]) == id(b):
        print i
        match = True
    i += 1

Upvotes: 0

Views: 27

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1124558

list.index() matches values by equality, not identity.

It is easy enough to write a helper function that uses a loop, testing with the is operator and the enumerate() function:

def index_by_identity(lst, target):
    for i, obj in enumerate(lst):
        if obj is target:
            return i
    # no object matches
    raise IndexError(target)

or, alternatively with the next() function and a generator expression:

def index_by_identity(lst, target):
    try:
        return next(i for i, obj in enumerate(lst) if obj is target)
    except StopIteration:
        # no object matches
        raise IndexError(target)

Demo:

>>> a = [3, 2]
>>> b = [3, 2]
>>> a is b
False
>>> c = [[4, 3], a, [5, 7], b, [6, 3]]
>>> def index_by_identity(lst, target):
...     for i, obj in enumerate(lst):
...         if obj is target:
...             return i
...     # no object matches
...     raise IndexError(target)
... 
>>> index_by_identity(c, b)
3
>>> def index_by_identity(lst, target):
...     try:
...         return next(i for i, obj in enumerate(lst) if obj is target)
...     except StopIteration:
...         # no object matches
...         raise IndexError(target)
... 
>>> index_by_identity(c, b)
3

Upvotes: 2

Related Questions