简体   繁体   English

在列表中查找第一个元素和索引匹配条件

[英]find first element and index matching condition in list

Consider this simple example考虑这个简单的例子

mylist = [-1,-2,3,4,5,6]

for idx, el in enumerate(mylist):
    if el > 0:
        myidx, myel = idx, el
        break

myidx, myel
Out[20]: (2, 3)

I am interested in finding the first index and the corresponding first element in a python list that matches a specific condition (here, this is simply > 0).我有兴趣在 python 列表中找到与特定条件匹配的第一个索引和相应的第一个元素(这里,这只是 > 0)。

In the code above, I loop over the elements using enumerate and then use the if clause to find the correct elements.在上面的代码中,我使用enumerate元素,然后使用 if 子句查找正确的元素。 This looks very cumbersome to me.这对我来说看起来很麻烦。 Is there a better way to do this?有一个更好的方法吗? Using a native python function for instance?例如,使用本机 python function?

Thanks!谢谢!

You could do it in a list comprehension.你可以在列表理解中做到这一点。 This is basically the same as your code but condensed into one line, and it builds a list of results that match the criteria.这与您的代码基本相同,但压缩为一行,它构建了一个符合条件的结果列表。

The first way gets all the matches第一种方法获取所有匹配项

mylist = [-1,-2,3,4,5,6]

results = [(i, el) for i, el in enumerate(mylist) if el > 0]

Another way would be to use a generator expression which is probably faster, and just unpack it.另一种方法是使用可能更快的生成器表达式,然后将其解压缩。 This gets the first one.这得到了第一个。

*next((i, el) for i, el in enumerate(mylist) if el > 0))

This loops the list and checks the condition, then puts the index and element into a tuple.这会循环列表并检查条件,然后将索引和元素放入一个元组中。 Doing this inside parentheses turns it into a generator, which is much faster because it hasn't actually got to hold everything in memory, it just generates the responses as you need them.在括号内执行此操作会将其变成一个生成器,这要快得多,因为它实际上并没有将所有内容保存在 memory 中,它只是根据您的需要生成响应。 Using next() you can iterate through them.使用next()你可以遍历它们。 As we only use next() once here it just generates the first match.因为我们在这里只使用一次 next() ,所以它只生成第一个匹配项。 Then we unpack it with *然后我们用*解压它

As there are two other valid answers here I decided to use timeit module to time each of them and post the results.由于这里还有另外两个有效答案,我决定使用 timeit 模块对每个答案进行计时并发布结果。 For clarity I also timed the OP's method.为清楚起见,我还对 OP 的方法进行了计时。 Here is what I found:这是我发现的:

import timeit
# Method 1 Generator Expression
print(timeit.timeit('next((i, el) for i, el in enumerate([-1,-2,3,4,5,6]) if el > 0)', number=100000))
0.007089499999999999

# Method 2 Getting index of True
print(timeit.timeit('list(x > 0 for x in [-1,-2,3,4,5,6]).index(True)', number=100000))
0.008104599999999997

# Method 3 filter and lambda
print(timeit.timeit('myidx , myel = list(filter(lambda el: el[1] > 0, enumerate([-1,-2,3,4,5,6])))[0]', number=100000))
0.0155314

statement = """
for idx, el in enumerate([-1,-2,3,4,5,6]):
    if el > 0:
        myidx, myel = idx, el
        break
"""

print(timeit.timeit(statement, number=100000))
0.04074070000000002

Something like this should work:像这样的东西应该工作:

l = [-1,-2,3,4,5,6]
list(x > 0 for x in l).index(True)
# Output: 2

To find all patters, we can use python built in functions using要查找所有模式,我们可以使用 python 内置函数

from itertools import filterfalse
f = filterfalse(lambda x: x[1] <= 0, enumerate(l))
print(list(f))
# [(2, 1), (3, 2), (4, 3)]

You can make use of the combination of lambda and filter like this:您可以使用lambdafilter的组合,如下所示:

mylist = [-1,-2,3,4,5,6]

myidx, myel = list(filter(lambda el: el[1] > 0, enumerate(mylist)))[0]
print("({}, {})".format(myidx, myel))

Explanation:解释:

The filter() function which offers an elegant way to filter out all the elements takes in a function and a list as arguments. filter() function 提供了一种优雅的方式来过滤掉所有元素,它采用 function 和 arguments 列表。 Here they are lambda and mylist .在这里它们是lambdamylist Since you want to get the corresponding index, we need to use enumerate to wrap up enumerate(mylist) .既然要获取对应的索引,我们需要使用enumerate来包裹enumerate(mylist)

Basically, enumerate(mylist) returns a tuple of an index and the corresponding value.基本上, enumerate(mylist)返回索引的元组和相应的值。 Our condition here is the comparison between the value and 0 so that's why we get el[1] instead of el[0] to compare with 0 .我们这里的条件是值和0之间的比较,所以这就是为什么我们使用el[1]而不是el[0]来与0进行比较。

The results will be casted to list .结果将被强制转换为list This list includes all the pairs (index, value) that meet our condition.该列表包括所有符合我们条件的对(index, value) Here we want to get the first pair so that's why we have [0] at the end.在这里,我们想要获得第一对,这就是为什么我们在末尾有[0]

Output: Output:

(2, 3)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM