第一个Python列表索引大于x?


80

在列表中找到大于x的第一个索引的最Python方式是什么?

例如,

list = [0.5, 0.3, 0.9, 0.8]

功能

f(list, 0.7)

会回来

2.

56
不要使用“列表”作为变量名...
mshsayem 2010年

11
您的意思是“ pythonic”。根据urbandictionary.com/define.php?term=Pythonesque,“ pythonesque ”的意思是“超现实,荒唐”,我认为这不是您要寻找的东西:P
Roberto Bonvallet 2010

1
这个问题是模棱两可的。答案2是因为0.9 > 0.7还是因为0.8 > 0.7?换句话说,您是按顺序搜索还是按值递增的顺序搜索?
Sergey Orshanskiy 2015年


我投票决定以重复形式结束此问题,而不是相反,因为较新的问题更为笼统。
Cristian Ciupitu

Answers:


114
next(x[0] for x in enumerate(L) if x[1] > 0.7)

29
+1:尽管我希望避免使用幻数:next(idx为idx,如果值> 0.7
则为

37
+1为简单起见next(),但出于可读性考虑:next(i for i,v in enumerate(L) if v > 0.7)
Hardy

13
虽然看起来很不错,但是没有结果的情况会引起混乱的StopIteration。
维吉尔·杜普拉斯

2
@flybywire:next()在2.6+中。next()在早期版本中调用Genex的方法。
伊格纳西奥·巴斯克斯

3
@Wim:但是您可以回归到评估整个序列。使用itertools.chain()而不是像这样添加列表。
伊格纳西奥·巴斯克斯

35

如果list是排序的话,那么bisect.bisect_left(alist, value)大型列表的速度要比next(i for i, x in enumerate(alist) if x >= value)


不错的答案-使用小的4元素排序列表对我来说肯定快5到6倍,但是,(不确定是否出错),但是当我使用timeit对其进行计时时,它使用了10000个元素numpy数组的长列表我发现它的速度大约是上面列表理解答案的两倍,这让我感到惊讶。
阿德里安·汤普金斯

1
@AdrianTompkins:您的基准测试出了点问题。bisect_left是O(log n),而listcomp是O(n),即,越大n,在bisect_left()侧面越多。我试图找到的索引500_000range(10**6)使用bisect_left()- > 3.75微秒,并使用genexpr用next()- > 51.0毫秒[10_000时间]较慢的预期。
jfs

16
filter(lambda x: x>.7, seq)[0]

4
-1:在技术上正确无误,但不要在列表理解更易读和性能更高的地方使用过滤器
truppo 2010年

filter(lambda x:x [1]> .7,enumerate(seq))[0] [0]-简单的线性搜索
lowtech 2013年

4
python 3中的@truppo过滤器返回一个生成器,因此它应该不比列表理解更差吗?我也发现这种方式比枚举解决方案更具可读性。
BubuIIC

关于这一点不好的一件事是,如果序列中没有大于.7的项,则会进入异常处理。
Brian C.

该解决方案在技术上不正确。问题作者问如何在列表中找到元素的索引。但是此解决方案将返回一条记录。在Python 3.8中,Eventmore的速度bisect_left()(最快)和慢enumerate()
Sergey Nevmerzhitsky

16
>>> alist= [0.5, 0.3, 0.9, 0.8]
>>> [ n for n,i in enumerate(alist) if i>0.7 ][0]
2

2
如果'x'大于列表中的任何其他值,它将失败
mshsayem 2010年

2
@mshsayem:在这种情况下问题定义不明确。失败可能是正确的事情。
S.Lott

@ S.Loot:好点。将其分配给变量时,如果不在列表中失败将导致可理解的错误IndexError: list index out of range。使用index = next[ n for n,i in enumerate(alist) if i>0.7 ]错误给出:NameError: name 'index' is not definednext速度稍快:时序差异为12.7 ns,而60 000个数字的时间差异为11.9 ns。
狮子座


4

另一个:

map(lambda x: x>.7, seq).index(True)

2

当我的清单很长时,我遇到了类似的问题。理解或基于过滤器的解决方案将贯穿整个清单。一旦条件第一次变为假,itertools.takewhile将中断循环:

from itertools import takewhile

def f(l, b): return len([x for x in takewhile(lambda x: x[1] <= b, enumerate(l))])

l = [0.5, 0.3, 0.9, 0.8]
f(l, 0.7)

为什么你不写def f(l,b):return len(list(takewhile(lambda x:x [1] <= b,enumerate(l))))?
阿沃·阿萨特里亚

2

我知道已经有了很多答案,但是有时我会觉得pythonic这个词被翻译成“单线”。

当我认为更好的定义更接近此答案时

“利用Python语言的功能来生成清晰,简洁和可维护的代码。”

尽管上面的一些答案很简洁,但我认为它们并不清楚,而且新手程序员需要一段时间才能理解,因此对于具有许多技能水平的团队来说,它们很难维护。

l = [0.5, 0.3, 0.9, 0.8]

def f(l, x):
    for i in l:
        if i >x: break
    return l.index(i)


f(l,.7)

要么

l = [0.5, 0.3, 0.9, 0.8]

def f(l, x):
    for i in l:
        if i >x: return l.index(i)



f(l,.7)

我认为以上内容对于新手来说很容易理解,并且仍然足够简洁,可以被任何资深python程序员接受。

我认为编写愚蠢的代码是积极的。


2

1)NUMPY SOLUTION,常规列表

如果您很乐意使用numpy,那么以下内容将适用于常规列表(排序或未排序):

numpy.argwhere(np.array(searchlist)>x)[0]

或者如果您需要答案作为列表:

numpy.argwhere(np.array(searchlist)>x).tolist()[0]

或者如果您需要答案作为整数索引:

numpy.argwhere(np.array(searchlist)>x).tolist()[0][0]

2)NUMPY SOLUTION,排序列表

但是,如果您的搜索列表已排序,则使用功能np.searchsorted会更加简洁明了

numpy.searchsorted(searchlist,x)

使用此函数的好处是,除了搜索单个值x之外,您还可以返回索引列表以获取值x的列表(在这种情况下,相对于列表理解而言,这非常有效)。


1
>>> f=lambda seq, m: [ii for ii in xrange(0, len(seq)) if seq[ii] > m][0]
>>> f([.5, .3, .9, .8], 0.7)
2

看起来很漂亮。但是从理论上讲,它将遍历整个列表,然后返回第一个结果(大于x),对吗?找到第一个结果后,有什么方法可以让它停下来吗?
c00kiemonster 2010年

遍历整个列表有什么问题?如果第一个大于0.7的值在列表的末尾附近,则没有任何区别。
ghostdog74

3
真正。但是在这种特殊情况下,我打算在其中使用该函数的列表很长,因此,我希望它在找到匹配项后立即退出遍历...
c00kiemonster 2010

不管它的长与短,如果第一个值是列表的最后第二个项目,您仍然必须遍历整个列表才能到达列表!
ghostdog74 2010年

4
@ ghostdog74:是的,但这不是让所有情况都成为最坏情况的原因。
UncleBens


-1

试试这个:

def Renumerate(l):
    return [(len(l) - x, y) for x,y in enumerate(l)]

示例代码:

Renumerate(range(10))

输出:

(10, 0)
(9, 1)
(8, 2)
(7, 3)
(6, 4)
(5, 5)
(4, 6)
(3, 7)
(2, 8)
(1, 9)

1
问题是“在列表中找到大于x的第一个索引”。
Gino Mempin
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.