我有一个数字输入列表:
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]
答案 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]