Lista de corte con índice dynamic en

Necesito cortar una lista usando índices dynamics negativos ([: -index]). Esto fue fácil hasta que me di cuenta de que si el valor de mi índice dynamic era 0, no se devolvían artículos, en lugar de devolver la lista completa. ¿Cómo puedo implementar esto de manera que cuando el índice es 0, devuelva la cadena completa? Mi código es muy largo y complicado, pero básicamente este ejemplo muestra el problema:

arr='test text' index=2 print arr[:-index] >>'test te' #Entire string minus 2 from the right index=1 print arr[:-index] >>'test tex' #Entire string minus 1 from the right index=0 print arr[:-index] >>'' #I would like entire string minus 0 from the right 

Nota: Estoy usando Python 2.7.

Otra posible solución para la diversión.

 >>> arr = [1, 2, 3] >>> index = 0 >>> arr[:-index or None] [1, 2, 3] >>> index = 1 >>> arr[:-index or None] [1, 2] 

Para obtener un mayor rendimiento en tipos de secuencia inmutables como cadenas, puede evitar dividir la secuencia por completo en el caso de que el índice sea 0 al verificar el valor del índice antes de la operación de división.

Aquí hay tres funciones para probar en términos de rendimiento:

 def shashank1(seq, index): return seq[:-index or None] def shashank2(seq, index): return index and seq[:-index] or seq def shashank3(seq, index): return seq[:-index] if index else seq 

Los dos últimos deberían ser mucho más rápidos en el caso de que el índice sea 0, pero puede ser más lento (o más rápido) en otros casos.


Código de referencia actualizado: http://repl.it/oA5

Nota: Los resultados dependen bastante de la implementación de Python.

Quita algo de la limpieza de la notación de corte, pero se podría hacer

 >>> arr[: len(arr) - 2] 'test te' >>> arr[: len(arr) - 1] 'test tex' >>> arr[: len(arr) - 0] 'test text' 

Puede usar None lugar de 0 para obtener la porción completa:

 >>> arr = [1, 2, 3] >>> index = 1 >>> arr[:-index if index else None] [1, 2] >>> index = 0 >>> arr[:-index if index else None] [1, 2, 3] 

Mis pruebas:

 import timeit def jonrsharpe(seq, index): return seq[:-index if index else None] def Cyber(seq, index): return seq[:len(arr) - index] def shashank(seq, index): return seq[:-index or None] if __name__ == '__main__': funcs = ('jonrsharpe', 'Cyber', 'shashank') arr = range(1000) setup = 'from __main__ import arr, {}'.format(', '.join(funcs)) for func in funcs: print func for x in (0, 10, 100, 1000): print x, print timeit.timeit('{}(arr, {})'.format(func, x), setup=setup) 

y resultados:

 jonrsharpe 0 2.9769377505 10 3.10071766781 100 2.83629358793 1000 0.252808797871 Cyber 0 3.11828875501 10 3.10177615276 100 2.82515282642 1000 0.283648679403 shashank 0 2.99515364824 10 3.11204965989 100 2.85491723351 1000 0.201558213116 

Como no podría dormir hasta que elegí la mejor respuesta correcta, probé el rendimiento de cada respuesta utilizando dos scripts diferentes además del proporcionado por @jonrsharpe.

Este es el código que utilicé para comparar el rendimiento entre las tres soluciones diferentes que utilizan el profile :

 import profile arr='test 123456789014' def jonrsharpe(index): global arr for c in range(1,100000,1): a=arr[:-index if index else None] def Cyber(index): global arr for c in range(1,100000,1): a=arr[:len(arr)-index] def shashank(index): global arr for c in range(1,100000,1): a=arr[:-index or None] def testf(): for index in (0,3,6,9): jonrsharpe(index) Cyber(index) shashank(index) if __name__ == '__main__': profile.run("testf()") 

Aquí está la salida:

 ncalls tottime percall cumtime percall filename:lineno(function) 799992 1.629 0.000 1.629 0.000 :0(len) 12 0.021 0.002 0.021 0.002 :0(range) 1 0.006 0.006 0.006 0.006 :0(setprofile) 1 0.000 0.000 4.390 4.390 :1() 0 0.000 0.000 profile:0(profiler) 1 0.000 0.000 4.396 4.396 profile:0(testf()) 4 2.114 0.529 3.750 0.937 test.py:12(Cyber) 4 0.307 0.077 0.313 0.078 test.py:19(shashank) 1 0.000 0.000 4.390 4.390 test.py:26(testf) 4 0.319 0.080 0.328 0.082 test.py:5(jonrsharpe) 

Otro método:

 import time if __name__ == '__main__': arr = '01234567890123456789012345678901234567890123456789'#range(1000) for x in (0, 10, 20, 30,40,49): print 'index=',x start=time.clock() for count in range(1000000): a=arr[:-x if x else None] print 'jonrsharpe=',round(time.clock()-start,4) start=time.clock() for count in range(1000000): a=arr[:len(arr)-x] print 'Cyber =',round(time.clock()-start,4) start=time.clock() for count in range(1000000): a=arr[:-x or None] print 'shashank =',round(time.clock()-start,4) 

Salida:

 index= 0 jonrsharpe= 0.4918 Cyber = 0.5341 shashank = 0.4269 index= 10 jonrsharpe= 0.4617 Cyber = 0.5334 shashank = 0.4105 index= 20 jonrsharpe= 0.4271 Cyber = 0.4562 shashank = 0.3493 index= 30 jonrsharpe= 0.4217 Cyber = 0.4548 shashank = 0.3264 index= 40 jonrsharpe= 0.4713 Cyber = 0.8488 shashank = 0.6458 index= 49 jonrsharpe= 0.6159 Cyber = 0.5663 shashank = 0.4312 

Dado que usaré esta línea de código un millón de veces, el rendimiento es muy importante, y la solución de @ Shashank fue la ganadora en la mayoría de los casos, aunque solo fuera un poco.