【问题标题】:Small python quirk: Finding the index of first and last number within boundaries in a list小python怪癖:查找列表边界内第一个和最后一个数字的索引
【发布时间】:2013-09-15 22:33:04
【问题描述】:

我遇到了一个烦人的小问题。我的问题是这样的:

我有一系列介于 0 和 1 之间的数字: [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]

还有两个边界,比如 0.25 和 0.75。

我需要一种快速而漂亮的方法来找到系列中第一个数字和最后一个数字的索引,它们在边界内,在本例中为 (2, 6)

到目前为止,我只提出了一种使用 for 循环和 break 命令的笨拙方法。

提前感谢您的帮助!

【问题讨论】:

  • 让我们看看你的版本。我们还能如何告诉您它是否好/我们是否有更好的方法?

标签: list python-2.7 indexing


【解决方案1】:

如果你可以使用 numpy:

import numpy as np
data = np.array([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])
max_b = .75
min_b = .25
wh = np.where((data < max_b)*(data > min_b))[0]
left, right =  wh[0], wh[-1] + 1

或者简单地说(感谢 dougal):

left, right = np.searchsorted(data, [min_b, max_b])

如果你不能:

import bisect

data = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]
max_b = .75
min_b = .25
left = bisect.bisect_left(data, min_b)
right = bisect.bisect_right(data, max_b)

右侧加或减 1,具体取决于您是希望 data[right] 在集合中,还是 data[left:right] 为您提供集合。

【讨论】:

  • 如果你用的是numpy,还不如用searchsorted(基本上和bisect一样)。
  • 漂亮,不知道有这个功能
  • 我现在只是在使用一个列表,但以后肯定会派上用场!
【解决方案2】:

如果您的数字序列始终排序,您可以使用the bisect module 对端点执行binary search

>>> a = [.1, .2, .3, .4, .5, .6, .7, .8, .9]
>>> import bisect
>>> bisect.bisect_left(a, 0.25)
2
>>> bisect.bisect_right(a, 0.75) - 1
6

bisect_left(a, x) 返回位置p 使得a[:p] 的每个元素都小于x,并且a[p:] 的每个元素都大于或等于x;这正是您想要的下限。

bisect_right 返回位置p 使得a[:p] 的每个元素都小于或等于x,并且a[p:] 都大于x。所以右边界需要减一才能得到最大位置&lt;= x

【讨论】:

  • 我还没有测试过,但是将第一部分的结果作为lo 参数传递给第二部分可能会有用:例如bisect_left(a, 0.75, 2)
  • @JonClements 没错,这应该会在第二个 bisect 通话中节省一点工作。
  • 好吧,在那个尺寸表上我对此表示怀疑——它更大,下限在很大程度上接近尾声,我想它会......但只是想我会提到它: )
  • 嗯,不会有伤害的。 :) 但是,是的,因为二进制搜索是 O(lg n),所以只有下界到端的数组比原始数组小一个数量级时才会有任何区别。 (模缓存效率问题,这可能无关紧要,因为 Python 列表无论如何都是指针数组。)
  • 感谢您的快速回复!这正是我一直在寻找的。我认为这种方法也很有效?
猜你喜欢
  • 2010-10-06
  • 2021-04-20
  • 2019-12-09
  • 2022-12-18
  • 2019-08-12
  • 1970-01-01
  • 1970-01-01
  • 2018-05-20
  • 2015-10-08
相关资源
最近更新 更多