简体   繁体   中英

Recursively searching through dictionary returning complete hirerachy

My problem statement is I have search query and I have to return the dictionary matching the query maintaining the hierarchy.

I am able to achieve the first. But I want to return the complete hierarchy right from starting, like below

Getting this output:

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

Expected output:

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

}

This is my sample input:

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

This I what I have tried till now

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)

I think you need to build your return value from the return value of any successful recursive call, rather than using a global list (which will cause all sorts of problems if you ever need to do multiple searches). You should return something with special meaning (like None ) if there's no match.

Try something like this:

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

The return None could be omitted, since None is the default return value for a function that doesn't return anything else. But I think it's better to be explicit when the None has some meaning, as it does here.

If you don't just want to find the first matching result, but all matching results, you'll want to replace the early return calls with some more subtle behavior that only returns a value if a match was found somewhere:

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

You could also return an empty dictionary on a failed match, rather than None . To do that, change the if result: if "Name" in data: lines near the end to the single line if result and "Name" in data: and do the return result unconditionally (unindent it and get rid of the else: return None block). Change the if x is not None check in the recursive case to if x .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM