Python:返回列表的第一个元素的索引,使得传递的函数为true

时间:2009-11-09 14:14:32

标签: python list function indexing

list.index(x)函数返回值为x的第一个项目列表中的索引。

是否有一个函数list_func_index(),类似于具有函数index()的{​​{1}}函数作为参数。函数f()在列表的每个元素f()上运行,直到e返回f(e)。然后True返回list_func_index()的索引。

Codewise:

e

有更优雅的解决方案吗? (以及该功能的更好名称)

6 个答案:

答案 0 :(得分:78)

您可以使用生成器在单行中执行此操作:

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

关于生成器的好处是它们只能计算到所需的数量。因此,请求前两个索引(几乎)同样简单:

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

但是,期望在最后一个索引之后出现StopIteration异常(这就是生成器的工作方式)。这在你的“先取”方法中也很方便,要知道没有找到这样的值--- list.index()函数会抛出ValueError。

答案 1 :(得分:12)

@Paul接受的答案是最好的,但这里有一个侧面思维的变体,主要用于娱乐和教学......:

>>> 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

本质上,X的目的是将“相等”的含义从正常变为“满足此谓词”,从而允许在各种情况下使用谓词来定义为检查相等 - 例如,它还允许您编码而不是if any(is_odd(x) for x in l):,而不是if X(is_odd) in l:,等等。

值得使用?当@Paul采用的更明确的方法同样方便时(特别是当更改为使用新的,有光泽的内置next函数而不是旧的,不太合适的.next方法时)我建议在对该答案的评论中),但在其他情况下,它(或其他变体的想法“调整平等的含义”,也许其他比较器和/或散列)可能是合适的。大多数情况下,值得了解这个想法,以避免有一天从头开始发明它; - )。

答案 2 :(得分:11)

一种可能性是内置enumerate功能:

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

通常会将您描述的函数称为“谓词”;某些问题会返回true或false。这就是我在我的例子中称之为pred的原因。

我还认为返回None会更好,因为这是问题的真正答案。如果需要,呼叫者可以选择在None上爆炸。

答案 3 :(得分:4)

不是一个单一的功能,但你可以很容易地做到:

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

如果您不想一次评估整个列表,可以使用itertools,但它不是那么漂亮:

>>> 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
>>> 

使用生成器表达式可能比itertools更具可读性。

在Python3中注意,mapfilter返回延迟迭代器,你可以使用:

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

答案 4 :(得分:2)

亚历克斯答案的一个变种。这样可以避免每次要使用X或任何谓词

时键入is_odd
>>> 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

答案 5 :(得分:1)

你可以用列表理解来做到这一点:

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

然后filterl将返回列表的所有成员,表达式为%2!= 0.我会说更优雅的方法......