2009-05-31 3 views
8

alle. Ich bin ein sehr, sehr neuer Programmierer. Meine Sprache der Wahl ist momentan Python und ich habe das Gefühl, dass ich ein gutes Gefühl dafür habe. Ich lerne gerade erst von Rekursion. (Übrigens, wenn jemand eine gute Anleitung dazu empfehlen könnte, lassen Sie es mich bitte wissen!) Nur damit Sie alle wissen, diese Frage ist sehr elementar und der Code, den ich poste, ist furchtbar, entsetzlich falsch.Freunde innerhalb eines bestimmten Grades der Trennung erreichen

Wie auch immer, ich versuche eine Funktion zu schreiben, die alle Freunde innerhalb eines bestimmten Grades bekommt. Wenn ich es als Grad 0 gebe, will ich nur mich. Wenn ich es gebe 1, will ich mich und alle meine Freunde. 2, ich will mich, meine Freunde und all ihre Freunde und so weiter.

Ich habe versucht, einige verschiedene Möglichkeiten, dies zu tun, aber keine Arbeit. Ich versuche mir vorzustellen, wie es in der Theorie funktionieren soll, und ich kann das auch nicht ganz verstehen, weil ich auf diesem Gebiet so unerfahren bin. Vielleicht kann eine freundliche Seele mir hier alle Möglichkeiten aufzeigen, wie dieser Code versagt, und dann erklären, wie man es richtig macht und/oder eine gute Anleitung zu diesem Thema empfiehlt. Hier gehts:

Es funktioniert nicht, und ich weiß, ich habe dumme, dumme Dinge getan. Jemand klopft mich bitte und zeigt mir in die richtige Richtung!

Danke.

+1

Sie einen Satz verwenden soll (http://docs.python.org/library/stdtypes. html # set) statt einer Liste. –

+0

+1 Matthäus. Wenn A Freund mit B ist und B Freund mit A, A, wird A.getFriends (5, []) zurückgeben [A, B, A, B, A, B] – NicDumZ

Antwort

13
friendList = friendList.append(self) 

Dies setzt friendList-None, bedingungslos, wie das ist, der unveränderliche Rückgabewert jeder append Methode der Liste - so, fix dass Seltsamkeit ersten ... -)

Sobald Sie behoben, dass Sie immer noch die Funktion reparieren müssen, so dass es immer mit return von etwas endet - "vom Ende fallen" gibt None zurück. ZB:

def getFriends(self,degree, friendList): 
    if degree == 0: 
     friendList.append(self) 
     return friendList 
    else: 
     friendList.append(self) 
     for each in self.friends: 
      each.getFriends(degree-1, friendList) 
     return friendList 

welche und deutlich die Doppelarbeit zu beseitigen Refactoring werden soll, kann (DRY, Do not Repeat Yourself, ist das Herz der Programmierung ...):

def getFriends(self,degree, friendList): 
    friendList.append(self) 
    if degree > 0: 
     for each in self.friends: 
      each.getFriends(degree-1, friendList) 
    return friendList 

PS: dass (die alist=alist.append(...) Ausgabe) genau wie ich im Jahr 2002 wieder in Kontakt mit meiner Frau Anna kam (wir waren nicht-ganz-Schatz Freunde vor vielen Jahren aber hatten einander aus den Augen verloren) - sie begann Python zu studieren, genau verwendet Dieses fehlerhafte Konstrukt konnte nicht verstehen, warum es fehlgeschlagen war - sah sich in der Python-Gemeinschaft um, sah und erkannte meinen Namen , schickte mir eine Mail, um danach zu fragen ... weniger als zwei Jahre später waren wir verheiratet, und bald darauf war sie das erste weibliche Mitglied der Python Software Foundation und mein Co-Autor in "Python Cookbook" 2nd ed. Also, natürlich habe ich einen unglaublichen Sweet Spot für diesen speziellen Python-Fehler ... ;-).

+1

Wow, Glückwunsch, Mann! Danke für den Tipp übrigens. Es kommt immer noch nirgends zurück, aber ich werde sehen, ob ich das verkraften kann. – Garrett

+1

Sobald Sie dieses Problem behoben haben, wird die Funktion "läuft aus dem Ende" (keine Rückgabeanweisung) und somit immer noch keine zurückgegeben - lassen Sie mich meine Antwort bearbeiten, um zu versuchen, dies zu beheben! –

+0

Es ist ein bisschen ärgerlich, dass append und sort None zurückgibt. Ich persönlich denke, es sollte die Liste wieder zurückgeben. – Unknown

1

Sie können friendList.append (self) in die Zeile vor dem if verschieben - Sie benötigen es in beiden Fällen. Sie müssen das Ergebnis auch nicht der Friendlist zuweisen - es ist ein Bug.

In Ihrem Algorithmus werden Sie wahrscheinlich dieselben Personen zweimal hinzufügen - wenn A ein Freund von B ist und B ein Freund von A. Sie müssen also eine Gruppe von Freunden behalten, die Sie bereits verarbeitet haben. Überprüfen Sie vor der Verarbeitung dieses Set und tun Sie nichts, wenn die Person bereits verarbeitet wurde.

+0

Danke, das macht es ein wenig prägnanter . Ich habe den Code so oft geändert, dass ich nicht wirklich darüber nachgedacht habe. In Bezug auf Duplikate, würde ich damit umgehen, nachdem ich das Ding überhaupt zur Arbeit bekommen habe. Ich weiß, dass es effizienter sein wird, wenn ich das tue, aber ich versuche, einen Schritt nach dem anderen zu machen. – Garrett

+1

Es wäre wahrscheinlich eine bessere Idee, die Objekte einfach zu einem Treeset oder ähnlichem hinzuzufügen; weniger Objekte zu verfolgen und all das. – Albinofrenchy

+0

Ich habe am Ende nur eine Klausel hinzugefügt, um nur self zur friendList hinzuzufügen, wenn self nicht bereits in der friendList ist. Wahrscheinlich nicht so effizient, aber darüber mache ich mir keine Sorgen. – Garrett

1

Ist Ihre Identität korrekt?Der Hauptteil der Methode sollte relativ zu ihrer Definition eingerückt sein

+0

Es ist richtig, ich denke, ich habe es einfach nicht richtig eingefügt. Trotzdem danke. :) – Garrett

+0

Die Einrückung wurde korrigiert. –

1

Es gibt keine return Erklärung in der else Klausel. Wenn also degree != 0 zurückgegeben wird, gibt diese Methode immer None zurück. Sie möchten das Ergebnis jedes rekursiven Aufrufs getFriends an Ihre friendList anhängen und dann friendList zurückgeben.

Übrigens, wenn Sie diesen Algorithmus schneller machen möchten, gibt es gut etablierte Methoden, um dies entweder mit Graph-Algorithmen oder Matrix-Manipulation zu tun. Wenn Sie beispielsweise Freundschaftsbeziehungen mit einer Adjazenzmatrix A darstellen und alle Personen finden möchten, die sich innerhalb von n Grad der Trennung voneinander befinden, können Sie B=A^n berechnen. Wenn B[i][j] > 0, dann i und j sind innerhalb n Grad der Trennung voneinander. Matrix-Multiplikation ist einfach mit einem Paket wie NumPy.

1

(Leider kann ich nicht kommentieren Alex Antwort ... noch)

Ich weiß nicht wirklich wie die Idee, dass GetFriends einen Wert zurückgibt, die nie verwendet wird. Es funktioniert zwar, aber es sieht ein bisschen faszinierend aus;) Auch der erste Aufruf von getFriends wäre self.getFriends (degree, []) was verwirrend ist: wenn du eine Liste von Freunden bekommst, warum würdest du als eine gehen Argument eine leere Liste, oder?

Aus Gründen der Klarheit, denke ich, dass ich diese etwas andere Version bevorzugen, die Funktion _getFriends Helfer mit:

def getFriends(self, degree): 
    friendList = [] 
    self._getFriends(degree, friendList) 
    return friendList 

def _getFriends(self, degree, friendList): 
    friendList.append(self) 
    if degree: 
     for friend in self.friends: 
      friend._getFriends(degree-1, friendList) 
+0

Ich mag das besser. Wird in Python so überladen? Ich kann dir nicht sagen, wie neu ich bin. ha ha. Vielen Dank! – Garrett

+0

Hallo + Es hat nichts mit Überladung zu tun :) GetFriends und _getFriends sind zwei völlig verschiedene Funktionen. _getFriends könnte _getFriendsHelper heißen. Der führende Unterstrich bedeutet "diese Funktion ist nicht öffentlich/eine Hilfsfunktion". Anders als Java erlaubt es immer noch externen Zugriff. Lies http://mail.python.org/pipermail/python-list/2002-February/127959.html darüber :) – NicDumZ

Verwandte Themen