Esta solución puede ser un poco exagerada para el póster original, pero pensé que compartiría el código que he estado usando para resolver este y otros problemas similares.
Es un poco largo (unas 90 líneas), pero si a menudo tiene esta necesidad, quiere un oneliner fácil de usar y necesita un entorno libre de python puro, entonces creo que podría ser útil.
Básicamente, lo único que tiene que hacer es pasar su lista a la función y decirle qué longitud que usted quiere que su nueva lista que sea, y la función, o bien:
- reducir el tamaño de su lista dejando caer los artículos si la nueva longitud es más pequeña, al igual que las respuestas anteriores ya sugeridas.
- tramo/exclusiva su lista (lo contrario de reducción) si la nueva longitud es mayor, con la opción añadida de que usted puede decidir si desea:
- interpolar linealmente BW los valores conocidos (elige automáticamente si la lista contiene enteros o flotadores)
- duplican cada valor para que ocupen un tamaño proporcional de la nueva lista (elegidos automáticamente si la lista contiene los no números)
- tire de los valores originales de separación y dejar huecos entre
Todo se recoge dentro de una función, por lo que si lo necesita solo copie y péguelo en su secuencia de comandos y puede comenzar a usarlo de inmediato.
Por ejemplo, usted podría decir:
origlist = [0,None,None,30,None,50,60,70,None,None,100]
resizedlist = ResizeList(testlist, 21)
print(resizedlist)
y obtener
[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]
Nota que las inexactitudes menores ocurrirán debido a las limitaciones de punto flotante. Además, escribí esto para Python 2.x, así que para usarlo en Python 3.x simplemente agregue una sola línea que diga xrange = range
.
Y aquí hay un ingenioso truco para interpolar entre los subelementos posicionados en una lista de listas. Así, por ejemplo, puede interpolar fácilmente entre tuplas de color RGB para crear un degradado de color de xn de pasos. Suponiendo una lista de tuplas de color RGB de 3 y una variable GRADIENTLENGTH deseado hacer esto con:
crosssections = zip(*rgbtuples)
grad_crosssections = (ResizeList(spectrum,GRADIENTLENGTH) for spectrum in crosssections)
rgb_gradient = [list(each) for each in zip(*grad_crosssections)]
Probablemente podría necesitar un buen número de optimizaciones, que tenía que hacer un poco de experimentación. Si crees que puedes mejorar, puedes editar mi publicación. Aquí está el código:
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
"""
#return input as is if no difference in length
if newlength == len(rows):
return rows
#set auto stretchmode
if stretchmethod == "not specified":
if isinstance(rows[0], (int,float)):
stretchmethod = "interpolate"
else:
stretchmethod = "duplicate"
#reduce newlength
newlength -= 1
#assign first value
outlist = [rows[0]]
writinggapsflag = False
if rows[1] == gapvalue:
writinggapsflag = True
relspreadindexgen = (index/float(len(rows)-1) for index in xrange(1,len(rows))) #warning a little hacky by skipping first index cus is assigned auto
relspreadindex = next(relspreadindexgen)
spreadflag = False
gapcount = 0
for outlistindex in xrange(1, newlength):
#relative positions
rel = outlistindex/float(newlength)
relindex = (len(rows)-1) * rel
basenr,decimals = str(relindex).split(".")
relbwindex = float("0."+decimals)
#determine equivalent value
if stretchmethod=="interpolate":
#test for gap
maybecurrelval = rows[int(relindex)]
maybenextrelval = rows[int(relindex)+1]
if maybecurrelval == gapvalue:
#found gapvalue, so skipping and waiting for valid value to interpolate and add to outlist
gapcount += 1
continue
#test whether to interpolate for previous gaps
if gapcount > 0:
#found a valid value after skipping gapvalues so this is where it interpolates all of them from last valid value to this one
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
#interpolate value
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 #basenr pluss interindex percent interpolation of diff to next item
elif stretchmethod=="duplicate":
relbwval = rows[int(round(relindex))] #no interpolation possible, so just copy each time
elif stretchmethod=="spread":
if rel >= relspreadindex:
spreadindex = int(len(rows)*relspreadindex)
relbwval = rows[spreadindex] #spread values further apart so as to leave gaps in between
relspreadindex = next(relspreadindexgen)
else:
relbwval = gapvalue
#assign each value
outlist.append(relbwval)
#assign last value
if gapcount > 0:
#this last value also has to interpolate for previous gaps
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
¿Puede elaborar un poco? Gracias. – Dave
Comience con un contador en 0. Mientras que el contador es menor que la longitud de la lista: ceda el elemento de la lista cuyo índice es el valor del contador, con piso, luego incremente el contador. –