### Question :

The `list.index(x)`

function returns the index in the list of the first item whose value is `x`

.

Is there a function, `list_func_index()`

, similar to the `index()`

function that has a function, `f()`

, as a parameter. The function, `f()`

is run on every element, `e`

, of the list until `f(e)`

returns `True`

. Then `list_func_index()`

returns the index of `e`

.

Codewise:

```
>>> def list_func_index(lst, func):
for i in range(len(lst)):
if func(lst[i]):
return i
raise ValueError('no element making func True')
>>> l = [8,10,4,5,7]
>>> def is_odd(x): return x % 2 != 0
>>> list_func_index(l,is_odd)
3
```

Is there a more elegant solution? (and a better name for the function)

##
Answer #1:

You could do that in a one-liner using generators:

```
next(i for i,v in enumerate(l) if is_odd(v))
```

The nice thing about generators is that they only compute up to the requested amount. So requesting the first two indices is (almost) just as easy:

```
y = (i for i,v in enumerate(l) if is_odd(v))
x1 = next(y)
x2 = next(y)
```

Though, expect a StopIteration exception after the last index (that is how generators work). This is also convenient in your “take-first” approach, to know that no such value was found — the list.index() function would throw ValueError here.

##
Answer #2:

One possibility is the built-in enumerate function:

```
def index_of_first(lst, pred):
for i,v in enumerate(lst):
if pred(v):
return i
return None
```

It’s typical to refer a function like the one you describe as a “predicate”; it returns true or false for some question. That’s why I call it `pred`

in my example.

I also think it would be better form to return `None`

, since that’s the real answer to the question. The caller can choose to explode on `None`

, if required.

##
Answer #3:

@Paul’s accepted answer is best, but here’s a little lateral-thinking variant, mostly for amusement and instruction purposes…:

```
>>> class X(object):
... def __init__(self, pred): self.pred = pred
... def __eq__(self, other): return self.pred(other)
...
>>> l = [8,10,4,5,7]
>>> def is_odd(x): return x % 2 != 0
...
>>> l.index(X(is_odd))
3
```

essentially, `X`

‘s purpose is to change the meaning of “equality” from the normal one to “satisfies this predicate”, thereby allowing the use of predicates in all kinds of situations that are defined as checking for equality — for example, it would also let you code, instead of `if any(is_odd(x) for x in l):`

, the shorter `if X(is_odd) in l:`

, and so forth.

Worth using? Not when a more explicit approach like that taken by @Paul is just as handy (especially when changed to use the new, shiny built-in `next`

function rather than the older, less appropriate `.next`

method, as I suggest in a comment to that answer), but there are other situations where it (or other variants of the idea “tweak the meaning of equality”, and maybe other comparators and/or hashing) may be appropriate. Mostly, worth knowing about the idea, to avoid having to invent it from scratch one day;-).

##
Answer #4:

Not one single function, but you can do it pretty easily:

```
>>> test = lambda c: c == 'x'
>>> data = ['a', 'b', 'c', 'x', 'y', 'z', 'x']
>>> map(test, data).index(True)
3
>>>
```

If you don’t want to evaluate the entire list at once you can use itertools, but it’s not as pretty:

```
>>> from itertools import imap, ifilter
>>> from operator import itemgetter
>>> test = lambda c: c == 'x'
>>> data = ['a', 'b', 'c', 'x', 'y', 'z']
>>> ifilter(itemgetter(1), enumerate(imap(test, data))).next()[0]
3
>>>
```

Just using a generator expression is probably more readable than `itertools`

though.

Note in Python3, `map`

and `filter`

return lazy iterators and you can just use:

```
from operator import itemgetter
test = lambda c: c == 'x'
data = ['a', 'b', 'c', 'x', 'y', 'z']
next(filter(itemgetter(1), enumerate(map(test, data))))[0] # 3
```

##
Answer #5:

A variation on Alex’s answer. This avoids having to type `X`

every time you want to use `is_odd`

or whichever predicate

```
>>> class X(object):
... def __init__(self, pred): self.pred = pred
... def __eq__(self, other): return self.pred(other)
...
>>> L = [8,10,4,5,7]
>>> is_odd = X(lambda x: x%2 != 0)
>>> L.index(is_odd)
3
>>> less_than_six = X(lambda x: x<6)
>>> L.index(less_than_six)
2
```

##
Answer #6:

you could do this with a list-comprehension:

```
l = [8,10,4,5,7]
filterl = [a for a in l if a % 2 != 0]
```

Then filterl will return all members of the list fulfilling the expression a % 2 != 0. I would say a more elegant method…