舍入数字在Python中可变数量范围内

时间:2014-06-05 02:10:27

标签: python list replace compression range

我有一个数字输入列表:

lst = [3.253, -11.348, 6.576, 2.145, -11.559, 7.733, 5.825]

我试图想办法用一个给定的数字替换列表中的每个数字,如果它落入一个范围。我想基于输入列表的最小值和最大值创建多个范围,并且输入数字将控制有多少范围。 例如,如果我说我想要在最小和最大之间等分的3个范围。

numRanges = 3
lstMin = min(lst)
lstMax = max(lst)
step = (lstMax - lstMin) / numRanges

range1 = range(lstMin, lstMin + step)
range2 = range(range1 + step)
range3 = range(range2 + step)

就在这里,有没有办法让数量范围由numRanges变量驱动? 后来我想拿输入列表,例如:

for i in lst:
    if i in range1:
        finalLst.append(1) #1 comes from range1 and will be growing if more ranges
    elif i in range2:
        finalLst.append(2) #2 comes from range2 and will be growing if more ranges
    else i in range3:
        finalLst.append(3) #3 comes from range2 and will be growing if more ranges

我现在看到这一切的方式全是"手册"并且我不确定如何使它更灵活,我可以指定多少范围和一个数字列表,让代码完成其余的工作。提前感谢您的帮助。

finalLst = [3, 1, 3, 3, 1, 3, 3]

2 个答案:

答案 0 :(得分:2)

这对于列表理解中的基本数学运算很容易:

numRanges = 3
lstMin = min(lst)
lstMax = max(lst) + 1e-12 # small value added to avoid floating point rounding issues
step = (lstMax - lstMin) / numRanges

range_numbers = [int((x-lstMin) / step) for x in lst]

这将为原始列表中的每个值提供一个整数,0表示该值落在第一个范围内,1是第二个,依此类推。它与您的代码几乎相同,但数字从0开始,而不是1(如果您真的想要1索引,可以在计算中粘贴+ 1

我添加到lstMax的小值有两个原因。第一个是确保浮点舍入问题不会使列表中的最大值产生numRange作为其范围索引而不是numRange-1(表示numRange范围)。另一个原因是如果列表仅包含单个值(可能重复多次),以便min(lst)max(lst)返回相同的内容,则避免除以零错误。

答案 1 :(得分:0)

Python有一个非常好的工具来完成这种称为bisect的工作。让我们说你的范围列表定义如下:

ranges = [-15, -10, -5, 5, 10, 15]

对于您的输入列表,您只需调用bisect,如下所示:

lst = [3.253, -11.348, 6.576, 2.145, -11.559, 7.733, 5.825]
results = [ranges[bisect(ranges, element)] for element in lst]

结果是

>>>[5, -10, 10, 5, -10, 10, 10]

然后,您可以使用python 2.7中的ranges = range(start,stop,step)或python 3.X中的ranges = list(range(start,stop,step))将其扩展到任意范围的任意列表

<强>更新

重新阅读您的问题,这可能更接近您正在寻找的内容(仍然使用bisect):

from numpy import linspace
from bisect import bisect_left

def find_range(numbers, segments):
    mx = max(numbers)
    mn = mn(numbers)
    ranges = linspace(mn, mx, segments)
    return [bisect_left(ranges, element)+1 for element in numbers]

>>> find_range(lst, 3)
[3, 2, 3, 3, 1, 3, 3]