2017-01-04 1 views
0

Meine Problemaussage ist, dass ich eine Suchabfrage habe und das Wörterbuch zurückgeben muss, das mit der Abfrage übereinstimmt, die die Hierarchie verwaltet.Rekursives Durchsuchen des Wörterbuchs, das den vollständigen Mietversuch zurückgibt

Ich bin in der Lage, die erste zu erreichen. Aber ich möchte die vollständige Hierarchie zurückzukehren rechts aus starten, wie unten

Erhalten dieser Ausgabe:

{"Name":"google search","items":[],"properties":{"id":1,"process":123} 

Erwartete Ausgabe:

{ 
    "items":[ 
    {'Name':'chrome','items': 
    [ 
     {"Name":"google search","items":[],"properties":{"id":1,"process":123}} 
    ] 
    }, 
    ] 

} 

Das ist mein Abtastwerteingang:

myinput = { 
    "items":[ 
    {'Name':'firefox','items':[],"properties":{"one":1,"two":2}}, 
    {'Name':'chrome','items':[ 
         {'Name':"stackoverflow","items":[],"properties":{"one":1,"two":2}}, 
         {"Name":"google search","items":[],"properties":{"id":1,"process":123}} 
         ], 
         "properties":{"one":1,"two":2}}, 
    {'Name':'new','items':[],"properties":{"one":1,"two":2}}, 
    {'Name':'new','items':[],"properties":{"one":1,"two":2}}, 
    ] 
} 

Das habe ich bis jetzt versucht

matched_items = [] 
def resursive_fun(Nodes, searchQuery): 
    for key, value in Nodes.iteritems(): 
     if isinstance(value, list): 
      for item in value: 
       matchValue = match_items(searchQuery, item['properties']) 
       if matchValue: 
        matched_items.append(item) 
       resursive_fun(item, searchQuery) 
    return matched_items 

searchDict = {"id": 1, "process": 123} 
resursive_fun(myinput, searchDict) 

Antwort

2

Ich glaube, Sie brauchen Ihre Rückgabewert der Rückgabewert eines jeden erfolgreichen rekursiven Aufruf zu bauen, anstatt eine globale Liste mit (die alle möglichen Probleme verursachen, wenn Sie jemals mehrere Suchen müssen tun). Sie sollten etwas mit besonderer Bedeutung (wie None) zurückgeben, wenn es keine Übereinstimmung gibt.

versuchen, etwas wie folgt aus:

def recursive_search(data, query): 
    if match_items(searchQuery, data["properties"]):   # base case 
     return data 

    if "items" in data and isinstance(data["items"], list):  # recursive case 
     for item in data["items"]: 
      x = recursive_search(item, query) 
      if x is not None:     # recursive search was successful! 
       return {"Name": data["Name"], "items": [x]} 

    return None       # if search is not successful, return None 

Die return None weggelassen werden könnte, da None ist der Standardrückgabewert für eine Funktion, die nichts anderes zurück. Aber ich denke, es ist besser, explizit zu sein, wenn die None eine Bedeutung hat, wie hier.

Wenn Sie nicht nur das erste übereinstimmende Ergebnis, sondern alle übereinstimmenden Ergebnisse finden möchten, sollten Sie die frühen return Aufrufe durch ein subtileres Verhalten ersetzen, das nur einen Wert zurückgibt, wenn irgendwo eine Übereinstimmung gefunden wurde:

def recursive_search(data, query): 
    result = {} 

    if if "properties" in data and match_items(searchQuery, data["properties"]): 
     result["properties"] = data["properties"] 

    if "items" in data and isinstance(data["items"], list): 
     for item in data["items"]: 
      result_items = [] 
      x = recursive_search(item, query) 
      if x is not None: 
       result_items.append(x) 
     if result_items:   # recursive search found at least one match 
      result["items"] = result_items 

    if result:  # some part of the search found a match (either here or deeper) 
     if "Name" in data: 
      result["Name"] = data["Name"] 
     return result 
    else: 
     return None 

könnten Sie auch ein leeres Wörterbuch auf einem ausgefallenen Spiel zurückzukehren, anstatt None. Um dies zu tun, ändern Sie die if result: if "Name" in data: Zeilen in der Nähe des Endes auf die einzige Zeile if result and "Name" in data: und tun Sie die return result bedingungslos (entfernen Sie es und den else: return None Block loszuwerden). Ändern Sie die if x is not None Überprüfung im rekursiven Fall auf if x.

+0

Das funktioniert gut. Aber wenn meine Suchanfrage mit mehr als einem Element in der Eingabe übereinstimmt, gibt dieser Algorithmus nicht alle Trefferergebnisse zurück. Beispiel: Wenn das Suchdikt 'searchDict = {" process ": 123}' ist, haben zwei meiner Objekte denselben Wert. In diesem Fall sollte es mir zwei Wörterbücher mit seiner Hierarchie zurückgeben. – vr22

+0

Sie können die Logik ein wenig ändern, um nicht kurzzuschließen, wenn Sie mehrere Übereinstimmungen behandeln müssen. Die einzige schwierige Sache in dieser Situation ist die Entscheidung, wie mit den Unterelementen eines übereinstimmenden Elements verfahren wird. Sollten sie immer dabei sein oder nicht? – Blckknght

+0

Unterartikel nicht unbedingt alle Male enthalten. Kannst du etwas mehr darüber erklären, wie man das Szenario mit mehreren Übereinstimmungen nicht kurzschließt? wäre sehr hilfreich für mich. Danke im Voraus. – vr22

Verwandte Themen