这个解决方案可能对原帖作者来说有点过于复杂,但我想分享一下我一直在使用的代码来解决这个和类似问题。
它有点冗长(大约90行),但如果你经常需要这样做,想要一个易于使用的单行代码,并且需要一个纯Python依赖环境,那么我认为它可能会有用。
基本上,你只需要将你的列表传递给函数,并告诉它你想要新列表的长度,函数将执行以下操作之一:
- 缩小你的列表,如果新长度更小,则删除项目,就像之前的答案建议的那样。
- 拉伸/放大你的列表(与缩小相反),如果新长度更大,还可以选择是否:
- 在已知值之间进行线性插值(如果列表包含整数或浮点数,则自动选择)
- 复制每个值,使它们占据新列表的比例大小(如果列表包含非数字,则自动选择)
- 拉开原始值,并在其中留下间隙
所有内容都包含在一个函数中,因此如果需要,只需将其复制并粘贴到脚本中即可立即开始使用。
例如,你可以这样说:
origlist = [0,None,None,30,None,50,60,70,None,None,100]
resizedlist = ResizeList(testlist, 21)
print(resizedlist)
并获取
[0, 5.00000000001, 9.9999999999900009, 15.0, 20.000000000010001, 24.999999999989999, 30, 35.0, 40.0, 45.0, 50.0, 55.0, 60.0, 65.0, 70, 75.000000000010004, 79.999999999989996, 85.0, 90.000000000010004, 94.999999999989996, 100]
请注意,由于浮点数限制,可能会出现小的不准确性。此外,我是为Python 2.x编写的,因此要在Python 3.x上使用它,只需添加一行代码,即
xrange = range
。
这里有一个巧妙的技巧,可以在列表的子列表中的位置之间进行插值。例如,您可以轻松地在RGB颜色元组之间进行插值,以创建x个步骤的颜色渐变。假设有一个包含3个RGB颜色元组的列表,并且有一个名为GRADIENTLENGTH的变量,则可以按如下方式执行:
crosssections = zip(*rgbtuples)
grad_crosssections = ( ResizeList(spectrum,GRADIENTLENGTH) for spectrum in crosssections )
rgb_gradient = [list(each) for each in zip(*grad_crosssections)]
可能需要进行一些优化,我不得不进行了相当多的实验。如果你觉得你可以改进它,请随意编辑我的帖子。以下是代码:
def ResizeList(rows, newlength, stretchmethod="not specified", gapvalue=None):
"""
Resizes (up or down) and returns a new list of a given size, based on an input list.
- rows: the input list, which can contain any type of value or item (except if using the interpolate stretchmethod which requires floats or ints only)
- newlength: the new length of the output list (if this is the same as the input list then the original list will be returned immediately)
- stretchmethod: if the list is being stretched, this decides how to do it. Valid values are:
- 'interpolate'
- linearly interpolate between the known values (automatically chosen if list contains ints or floats)
- 'duplicate'
- duplicate each value so they occupy a proportional size of the new list (automatically chosen if the list contains non-numbers)
- 'spread'
- drags the original values apart and leaves gaps as defined by the gapvalue option
- gapvalue: a value that will be used as gaps to fill in between the original values when using the 'spread' stretchmethod
"""
if newlength == len(rows):
return rows
if stretchmethod == "not specified":
if isinstance(rows[0], (int,float)):
stretchmethod = "interpolate"
else:
stretchmethod = "duplicate"
newlength -= 1
outlist = [rows[0]]
writinggapsflag = False
if rows[1] == gapvalue:
writinggapsflag = True
relspreadindexgen = (index/float(len(rows)-1) for index in xrange(1,len(rows)))
relspreadindex = next(relspreadindexgen)
spreadflag = False
gapcount = 0
for outlistindex in xrange(1, newlength):
rel = outlistindex/float(newlength)
relindex = (len(rows)-1) * rel
basenr,decimals = str(relindex).split(".")
relbwindex = float("0."+decimals)
if stretchmethod=="interpolate":
maybecurrelval = rows[int(relindex)]
maybenextrelval = rows[int(relindex)+1]
if maybecurrelval == gapvalue:
gapcount += 1
continue
if gapcount > 0:
startvalue = outlist[-1]
endindex = int(relindex)
endvalue = rows[endindex]
gapstointerpolate = gapcount
allinterpolatedgaps = Resize([startvalue,endvalue],gapstointerpolate+3)
outlist.extend(allinterpolatedgaps[1:-1])
gapcount = 0
writinggapsflag = False
currelval = rows[int(relindex)]
lookahead = 1
nextrelval = rows[int(relindex)+lookahead]
if nextrelval == gapvalue:
if writinggapsflag:
continue
relbwval = currelval
writinggapsflag = True
else:
relbwval = currelval + (nextrelval - currelval) * relbwindex
elif stretchmethod=="duplicate":
relbwval = rows[int(round(relindex))]
elif stretchmethod=="spread":
if rel >= relspreadindex:
spreadindex = int(len(rows)*relspreadindex)
relbwval = rows[spreadindex]
relspreadindex = next(relspreadindexgen)
else:
relbwval = gapvalue
outlist.append(relbwval)
if gapcount > 0:
startvalue = outlist[-1]
endvalue = rows[-1]
gapstointerpolate = gapcount
allinterpolatedgaps = Resize([startvalue,endvalue],gapstointerpolate+3)
outlist.extend(allinterpolatedgaps[1:-1])
outlist.append(rows[-1])
gapcount = 0
writinggapsflag = False
else:
outlist.append(rows[-1])
return outlist