2015-05-13 20 views
5

Ich muss eine Liste mit negativen dynamischen Indizes ([: -Index]) Slice Slice. Das war einfach, bis ich erkannte, dass, wenn der Wert meines dynamischen Index 0 war, keine Elemente zurückgegeben wurden, anstatt die gesamte Liste zurückzugeben. Wie kann ich das so implementieren, dass bei einem Index von 0 der gesamte String zurückgegeben wird? Mein Code ist sehr lang und kompliziert, aber im Grunde dieses Beispiel zeigt das Problem:List Slicing mit dynamischen Index auf [: Index]

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 

Hinweis: Ich verwende Python 2.7.

+0

Ist diese Linie possbly ein Tippfehler ?: >> ‚test te‘ #Entire Zeichenfolge minus 1 von rechts Es mir gleich wie die Zeile mit dem Index sieht = 2 und es fühlt sich mir, als ob es sein sollte show 'test tex' –

+0

ja, ich habe den Tippfehler behoben –

Antwort

7

Eine andere mögliche Lösung für Spaß.

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

Für eine höhere Leistung auf unveränderlichen Sequenztypen wie Strings, können Sie die Reihenfolge ganz im Fall Aufschneiden vermeiden, dass Index 0 durch den Wert des Index vor der Schichtbetrieb zu überprüfen.

Hier drei Funktionen in Bezug auf Leistung zu testen:

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 

Die beiden letzteren viel schneller im Fall sein sollte, wo der Index 0 ist, kann aber langsamer (oder schneller) sein in anderen Fällen.


Überarbeitete Benchmark-Code:http://repl.it/oA5

Hinweis: Die Ergebnisse hängen ziemlich viel auf der Python-Implementierung.

6

Es Art nimmt von der Reinheit der Scheibe Notation weg, aber man konnte

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

Sie können None tun verwenden, anstatt 0 die volle Scheibe zu bekommen:

>>> 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] 

Meine Prüfung:

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) 

und Ergebnisse:

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 
+0

Dies scheint die beste Antwort bis jetzt zu sein. Ich habe die Geschwindigkeit getestet und es ist 15 mal schneller als Cyber's Lösung –

+0

@AndresLa Meine Tests zeigen, dass alle 3 Code-Schnipsel ähnliche Geschwindigkeiten haben. Jon und ich sind * ein bisschen * schneller als Cyber's für Nicht-Null-Indizes, aber es ist nicht annähernd 15x so schnell. – Shashank

+0

@AndresLa Ich sehe Shashank ähnlich; die Leistung (mit ['timeit'] (https://docs.python.org/2/library/timeit.html)) ist ziemlich konsistent über die drei (Cyber ​​ist vielleicht ~ 3% langsamer). Ich würde erwarten, dass Shashank am schnellsten ist, wenn man ['dis'] (https://docs.python.org/2/library/dis.html) anwendet, aber das wird durch die Leistung nicht bestätigt. – jonrsharpe

1

Da ich nicht schlafen konnte, bis ich die beste Antwort gewählt hatte, testete ich die Leistung jeder Antwort mit zwei verschiedenen Skripten zusätzlich zu der von @jonrsharpe.

Dies ist der Code, den ich verwendet, Leistung zwischen den drei verschiedenen Lösungen vergleichen profile mit:

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()") 

Hier ist der Ausgang:

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 <string>:1(<module>) 
    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) 

Eine andere Methode:

import time 

if __name__ == '__main__': 
    arr = ''#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) 

Ausgabe:

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 

Da ich diese Codezeile millionenfach verwenden werde, ist die Leistung sehr wichtig, und die Lösung von @ Shashank war in den meisten Fällen der Gewinner, auch wenn es nur ein bisschen war.

+2

Beachten Sie, dass ich dies zu einem Community Wiki gemacht habe; Ich werde keine Wiederholung davon verdienen und jeder kann es bearbeiten, um Vergleiche für zusätzliche Methoden hinzuzufügen. – jonrsharpe