Find the index of an item in a list of lists

I'd do something like this:

[(i, colour.index(c))
 for i, colour in enumerate(colours)
 if c in colour]

This will return a list of tuples where the first index is the position in the first list and second index the position in the second list (note: c is the colour you're looking for, that is, "#660000").

For the example in the question, the returned value is:

[(0, 0)]

If you just need to find the first position in which the colour is found in a lazy way you can use this:

next(((i, colour.index(c))
      for i, colour in enumerate(colours)
      if c in colour),
     None)

This will return the tuple for the first element found or None if no element is found (you can also remove the None argument above in it will raise a StopIteration exception if no element is found).

Edit: As @RikPoggi correctly points out, if the number of matches is high, this will introduce some overhead because colour is iterated twice to find c. I assumed this to be reasonable for a low number of matches and to have an answer into a single expression. However, to avoid this, you can also define a method using the same idea as follows:

def find(c):
    for i, colour in enumerate(colours):
        try:
            j = colour.index(c)
        except ValueError:
            continue
        yield i, j

matches = [match for match in find('#660000')]

Note that since find is a generator you can actually use it as in the example above with next to stop at the first match and skip looking further.


Using enumerate() you could write a function like this one:

def find(target):
    for i,lst in enumerate(colours):
        for j,color in enumerate(lst):
            if color == "#660000":
                return (i, j)
    return (None, None)

It would be perhaps more simple using numpy:

>>> import numpy
>>> ar = numpy.array(colours)
>>> numpy.where(ar=="#fff224")
(array([2]), array([1]))

As you see you'll get a tuple with all the row and column indexes.