Frage

Ich habe versucht, mir über eine Möglichkeit nachzudenken, eine hierarchische Struktur zu durchqueren, wie eine verknüpfte Liste, die einen Listenausdruck verwendet, aber nichts, was zu funktionieren scheint.

Grundsätzlich möchte ich diesen Code konvertieren:

p = self.parent
names = []
while p:
  names.append(p.name)
  p = p.parent
print ".".join(names)

in einen Ein-Liner wie:

print ".".join( [o.name for o in <???>] )

Ich bin mir nicht sicher, wie ich den Traversal in der machen soll ??? Teil jedoch, allgemein (wenn es überhaupt möglich ist). Ich habe mehrere Strukturen mit ähnlichen .parent Geben Sie Attribute ein und möchten nicht eine Ertragsfunktion für jeden schreiben.

Bearbeiten:

Ich kann das nicht benutzen __iter__ Methoden des Objekts selbst, weil es bereits zum Iterieren über die im Objekt selbst enthaltenen Werte verwendet wird. Die meisten anderen Antworten, mit Ausnahme von Liori, hardcode den Attributnamen, was ich vermeiden möchte.

Hier ist meine Anpassung auf der Grundlage von Lioris Antwort:

import operator
def walk(attr, start):
  if callable(attr):
    getter = attr
  else:
    getter = operator.attrgetter(attr)

  o = getter(start)
  while o:
    yield o
    o = getter(o)
War es hilfreich?

Lösung

Wenn Sie möchten, dass Ihre Lösung allgemein ist, verwenden Sie eine allgemeine Techique. Dies ist ein fester Punkt wie Generator:

def fixedpoint(f, start, stop):
    while start != stop:
        yield start
        start = f(start)

Es gibt einen Generator zurück, der Start, f (Start), F (f (Start)), F (f (f (Start))), ..., solange keiner dieser Werte gleich gestoppt ist.

Verwendungszweck:

print ".".join(x.name for x in fixedpoint(lambda p:p.parent, self, None))

Meine persönliche Helfer-Bibliothek hat jahrelang eine ähnliche fixePoint-ähnliche Funktion ... es ist ziemlich nützlich für schnelle Hacks.

Andere Tipps

Das, was ich mir vorstellen kann, ist, einen übergeordneten Generator zu erstellen:

# Generate a node's parents, heading towards ancestors
def gen_parents(node):
   node = node.parent
   while node:
      yield node
      node = node.parent

# Now you can do this
parents = [x.name for x in gen_parents(node)]
print '.'.join(parents)

Listenverständnis funktioniert mit Objekten, die Iteratoren sind (haben die nächste () Methode). Sie müssen einen Iterator für Ihre Struktur definieren, um ihn so zu iterieren.

Ihre LinkedList muss iterbar sein, damit sie ordnungsgemäß funktioniert.

Hier ist eine gute Ressource. (PDF -Warnung) Es ist sowohl für Iteratoren als auch für Generatoren sehr ausführlich.

Sobald Sie das tun, können Sie dies einfach tun:

print ".".join( [o.name for o in self] )
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top