2016-07-21 4 views
0

Ich habe eine Liste von Python-Objekte:Was ist ein effizienter Weg, um vorherige und nächste Werte einer Schleifenliste von Objekten in Python zurückzugeben?

fruits = [ 'apple', 'orange', 'banana', 'grape', 'cherry' ] 

Ich habe derzeit eine for Schleife in einer Klassenmethode, die „prev_fruit“ und „next_fruit“ Objekte für ein bestimmtes Objekt zurückgibt:

def get_prev_next(self, fruit_list): 
    prev_fruit = next_fruit = None 
    fruit_list_length = len(fruit_list) 
    for idx, fruit in enumerate(fruit_list): 
     if fruit == self: 
      if idx > 0: 
       prev_fruit = fruit_list[idx-1] 
      if idx < (fruit_list_length-1): 
       next_fruit = fruit_list[idx+1] 
    return prev_fruit, next_fruit 

Diese funktioniert, obwohl es wahrscheinlich effizientere Möglichkeiten gibt, dies zu tun (worüber ich glücklich bin).

Ich möchte jetzt die Liste optional "Schleifen" (vorher für den ersten Index ist der letzte und der nächste Index für die letzte ist zuerst).

def get_prev_next(self, fruit_list, looping=False): 
    ... 

Was ist eine effiziente Möglichkeit, dies auf Listen von Objekten mit 1-10000 Werten zu tun?

„effizient“ ist nicht unbedingt „effizienteste“ als Code Lesbarkeit und Portabilität ist ein Faktor - ich will nicht den Ansatz von sechs Monaten ab jetzt

+1

Sie können die Objekte Teil einer [Linked List] machen (http://stackoverflow.com/questions/280243/python-linked-list)? –

+0

1-10000 Werte ... Sind alle einzigartig? Wenn Sie nach einem Index für einen Wert suchen, spielt es eine Rolle, ob er nur den ersten Wert zurückgibt oder ob Sie alle Vorkommen benötigen. – chapelo

+0

um genauer zu sein, sind die Listen Django-Abfragesätze, die eine Liste von Objekten zurückgeben - die Frage wurde mit dem Wunsch geschrieben, sie etwas generischer zu machen - dh. Das Ändern der Datenstruktur und des Refactorings ist nicht wirklich eine Lösung, die praktikabel ist - die Frage ist nicht, wie man es effizienter macht, sondern wie man es optional effizient macht – mogga

Antwort

0

umlernen Wenn die Eingabe eine Liste ist , dann bist du Art stecken die Liste für den Index der Frucht zu suchen, die Sie haben und dann die vorherigen und nächsten diejenigen aus, dass immer ...

def forgiving_getitem(lst, ix, default=None): 
    if 0 <= ix < len(lst): 
     return lst[ix] 
    else: 
     return default 

ix = fruit_list.index(self) 
previous = forgiving_getitem(fruit_list, ix - 1) 
next = forgiving_getitem(fruit_list, ix + 1) 

Leider ist dies O (N) Laufzeitkomplexität hat . Wenn Sie dies häufig mit der gleichen fruit_list tun, ist es möglicherweise besser, eine andere Datenstruktur (z. B. eine doppelt verknüpfte Liste) zu erstellen, bei der jeder Knoten die Frucht und die vorherigen und nächsten Früchte trägt. In diesem Fall ist O (1) das vorherige und das nächste zu erhalten, und Sie müssen nur O (N) Zeit damit verbringen, die Knoten an erster Stelle zu konstruieren, jedoch könnte ein anderes Code-Refactoring involviert sein, um mit Knoten anstelle von Früchten zu arbeiten direkt ...

+0

Aber wenn Sie die vorherigen und nächsten Indizes in einem Array kennen, * Zugriff auf sie ist immer noch Zeit, nicht? Aber die Iteration über das Array ist genauso linear wie bei einer verknüpften Liste. All die verknüpfte Struktur gibt Ihnen wirklich eine praktische Möglichkeit, auf das Vorhergehende und das Nächste zuzugreifen. Dies kann jedoch durch Verwendung eines Arrays mit der gleichen zeitlichen Komplexität erreicht werden. Tatsächlich ist der Zugriff auf einen bestimmten Index in Ihrem Array linear für verknüpfte Listen! –

+0

@ juanpa.arrivillaga - nein, du verpasst den Punkt dessen, was ich sage. Wenn Sie die verknüpfte Liste nach _find_ der Frucht suchen müssen, ist es natürlich O (N). OP hat dieses Problem jedoch bereits im Originalcode (woher kommt die Frucht ['self']?). Ich befürworte, dass anstatt einzelne Früchte als "Selbst" zu umgehen, mit Knoten zu arbeiten, die Referenzen zu Früchten enthalten. – mgilson

+0

Ah, OK. Aha. Das wird wahrscheinlich, wie Sie gesagt haben, ein erhebliches Refactoring beinhalten. –

Verwandte Themen