Home > Back-end >  Find a specific value in a large tree of sublists
Find a specific value in a large tree of sublists

Time:09-21

I have some code that generates a list that looks something like this:

chrs = [[["a",["b","c"]],["d","e"],"f"],["g",[["h","i"],"j"]]]

Now I need to find a specific value in some kind of list like this.
I wrote some code to do this, but it seems to get stuck in an infinite loop:

def locate_value(v,chrs):                       #
    checked=[[]]                                # Set up the values
    index_list=[]                               #
    inside=0                                    #
    cur=[0,0]                                   #
                                                #
    while True:                                 #
        if chrs[cur[0]] == v:                   # If found, end the loop and return the index_list
            return index_list                   #
                                                #
        if type(chrs[cur[0]]) != list:          # If the current is not a list, skip this one
            checked[inside].append(cur[0])      #
            index_list = []                     #
                                                #
        else:                                   #
            try:                                #
                if cur[0] in gone[inside]:      # If the current has been done before, skip it
                    cur[0]  = 1                 #
                                                #
                else:                           # And if not, move 1 space deeper
                    checked.append([])          #
                    index_list.append(cur[0])   #
                    cur[1] = cur[0]             #
                    cur[0] = 0                  #
                    inside  = 1                 #
                                                #
            except IndexError:                  # And if a sublist is fully checked, block it too
                checked[inside].append(cur[1])  #



print(locate_value("e",[[["a",["b","c"]],["d","e"],"f"],["g",[["h","i"],"j"]]]))

Editing me just realised how bad this code is

In this example, the function locate_value should return [0, 1, 1], as list[0][1][1] is "e"

But when I run this, I get stuck in an infinite loop Can anyone tell me what is wrong, and maybe give me some code that actually works for once.

The list is made with user input, so I have no idea how deep it is.
Though a python-3 only solution is fine, I would prefer one that supports python-2, too.

CodePudding user response:

Use a recursion function:

def locate_value(v, chrs, idx=[]):
    for j, i in enumerate(chrs):
        if isinstance(i, list):
            yield from find(v, i, idx   [j])
        elif i == v:
            yield idx   [j]

Another version to keep your original signature function:

def locate_value(v, chrs):
    for j, i in enumerate(chrs):
        if isinstance(i, list):
            yield from ([j, *idx] for idx in locate_value(v, i))
        elif i == v:
            yield [j]

Output:

>>> list(locate_value('e', chrs, []))
[[0, 1, 1]]

# case of multiple 'e'
# chrs = [[["a",["b","c"]],["d","e"],"f"],["g",[["h","e"],"j"]]]

>>> list(locate_value('e', chrs))
[[0, 1, 1], [1, 1, 0, 1]]

Greatly improved by @tobias_k

CodePudding user response:

The following will work:

def locate_value(v, chrs):
    if v == chrs:
        return []
    if not isinstance(chrs, list):
        raise IndexError
    for i, c in enumerate(chrs):
        try:
            return [i]   locate_value(v, c)
        except IndexError:
            pass
    raise IndexError


locate_value("e", [[["a",["b","c"]],["d","e"],"f"],["g",[["h","i"],"j"]]])
# [0, 1, 1]

Note that str objects are iterables themselves, so recursively keeping iterating their elements (strings yet again) will never end.

  • Related