Python:返回列表的第一个元素的索引,该列表使传递的函数tru
list_func_index()函数返回值为x的第一项列表中的索引。
是否有一个函数list_func_index(),类似于具有参数f()的index()函数。 在列表的每个元素e上运行函数f(),直到f(e)返回True。然后list_func_index()返回索引e。
按代码:
>>> 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
有没有更优雅的解决方案? (以及该函数的更好的名称)
6个解决方案
86 votes
您可以使用生成器在单行代码中做到这一点:
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。
Paul answered 2020-02-14T13:17:02Z
12 votes
@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
本质上,next的目的是将“平等”的含义从正常谓词更改为“满足此谓词”,从而允许在定义为检查相等性的所有情况下使用谓词-例如,它还将 让您编码,而不是.next,较短的if X(is_odd) in l:,依此类推。
值得使用吗? 当@Paul采取的更明确的方法同样方便时(特别是当更改为使用新的,内置的闪亮的next函数而不是较旧的,不太合适的.next方法时,并不是这样),正如我在对该答案的评论中建议的那样 ),但在其他情况下(或“调整相等的含义”的思想的其他变体,以及其他比较器和/或哈希)可能比较合适。 通常,值得了解这个主意,避免有一天不得不从头开始发明它;-)。
Alex Martelli answered 2020-02-14T13:17:32Z
11 votes
一种可能是内置的枚举功能:
def index_of_first(lst, pred):
for i,v in enumerate(lst):
if pred(v):
return i
return None
通常将类似您所描述的函数称为谓词的函数。 对于某些问题,它返回true或false。 这就是为什么在我的示例中将其称为None。
我也认为最好返回None,因为这是问题的真正答案。 如果需要,呼叫者可以选择在None上爆炸。
Jonathan Feinberg answered 2020-02-14T13:18:02Z
4 votes
不是一个功能,但是您可以轻松完成:
>>> 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
>>>
但是,仅使用生成器表达式可能比map更易读。
请注意,在Python3中,map和filter返回惰性迭代器,您可以使用:
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
Steve Losh answered 2020-02-14T13:18:35Z
2 votes
您可以通过列表理解来做到这一点:
l = [8,10,4,5,7]
filterl = [a for a in l if a % 2 != 0]
然后filterl将返回满足表达式%2!= 0的列表的所有成员。我想说一个更优雅的方法...
Vincent Osinga answered 2020-02-14T13:18:59Z
2 votes
亚历克斯答案的变化。 这样可以避免每次要使用is_odd或任何谓词时都不必键入X
>>> 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
John La Rooy answered 2020-02-14T13:19:19Z