【问题标题】:Finding the indices of matching elements in list in Python在Python中查找列表中匹配元素的索引
【发布时间】:2023-03-24 09:38:01
【问题描述】:

我有一长串从 1 到 5 的浮点数,称为“平均值”,我想返回小于 a 或大于 b 的元素的索引列表

def find(lst,a,b):
    result = []
    for x in lst:
        if x<a or x>b:
            i = lst.index(x)
            result.append(i)
    return result

matches = find(average,2,4)

但令人惊讶的是,“matches”的输出中有很多重复,例如[2, 2, 10, 2, 2, 2, 19, 2, 10, 2, 2, 42, 2, 2, 10, 2, 2, 2, 10, 2, 2, ...]

为什么会这样?

【问题讨论】:

标签: python list indexing find


【解决方案1】:

您正在使用.index(),它只会在列表中找到您的值的第一次出现。因此,如果您在索引 2 和索引 9 处具有值 1.0,那么 .index(1.0)始终返回 2,无论 1.0 在列表中出现多少次。

改为使用enumerate() 为循环添加索引:

def find(lst, a, b):
    result = []
    for i, x in enumerate(lst):
        if x<a or x>b:
            result.append(i)
    return result

你可以把它折叠成一个列表理解:

def find(lst, a, b):
    return [i for i, x in enumerate(lst) if x<a or x>b]

【讨论】:

  • 现在我完全明白了。列表推导真的很好用,我还在尝试在 Python 中适应这种紧凑的形式。您的回答非常好,非常感谢!
  • 有趣的是,重复的错误结果似乎对我以后的使用效果很好,因为我想用它来提取大矩阵的列。似乎重复不会影响切片。
  • 您仍然会从列表中获得正确的值,相同的值位于索引 2 和任何后面的索引处。但这是一个等待发生的错误,它会在代码中的其他位置咬你。
【解决方案2】:

如果你经常做这种事情,你应该考虑使用numpy

In [56]: import random, numpy

In [57]: lst = numpy.array([random.uniform(0, 5) for _ in range(1000)]) # example list

In [58]: a, b = 1, 3

In [59]: numpy.flatnonzero((lst > a) & (lst < b))[:10]
Out[59]: array([ 0, 12, 13, 15, 18, 19, 23, 24, 26, 29])

针对Seanny123的问题,我使用了这个计时码:

import numpy, timeit, random

a, b = 1, 3

lst = numpy.array([random.uniform(0, 5) for _ in range(1000)])

def numpy_way():
    numpy.flatnonzero((lst > 1) & (lst < 3))[:10]

def list_comprehension():
    [e for e in lst if 1 < e < 3][:10]

print timeit.timeit(numpy_way)
print timeit.timeit(list_comprehension)

numpy 版本快 60 倍以上。

【讨论】:

  • 与仅进行列表理解相比,性能比较是什么?另外,为什么使用numpy.flatnonzero 而不是numpy.where
  • 在我手中快了 60 倍以上。 flatnonzerowhere 简单,这里;您不需要从元组中提取索引数组。
【解决方案3】:
>>> average =  [1,3,2,1,1,0,24,23,7,2,727,2,7,68,7,83,2]
>>> matches = [i for i in range(0,len(average)) if average[i]<2 or average[i]>4]
>>> matches
[0, 3, 4, 5, 6, 7, 8, 10, 12, 13, 14, 15]

【讨论】:

  • 这根本不是 OP 想要的。
猜你喜欢
  • 1970-01-01
  • 2021-06-25
  • 2021-05-19
  • 1970-01-01
  • 2020-12-05
  • 2018-12-29
  • 2021-07-16
  • 2016-02-29
  • 2019-11-11
相关资源
最近更新 更多