Find index of nested item in python

后端 未结 3 1213
醉话见心
醉话见心 2021-01-22 02:27

I\'ve been working with some relatively complex arrays such as:

array = [ \"1\", 2, [\"4\", \"5\", (\"a\", \"b\")], (\"c\", \"d\")]

and I was l

相关标签:
3条回答
  • 2021-01-22 02:49

    array = [ "1", 2, ["4", "5", ("a", "b")], ("c", "d")]

    def find_index(array, item, index=None):
        if not index:
            index = []
        try:
            i = array.index(item)
        except:
            for new_array in array:
               if hasattr(new_array, '__iter__'):
                   i = find_index(new_array, item, index+[array.index(new_array)])
                   if i:
                       return i
        else:
            return index + [i]
        return None
    

    This gives:

    >>> find_index(array, 1)
    >>> find_index(array, "1")
    [0]
    >>> find_index(array, 2)
    [1]
    >>> find_index(array, "4")
    [2, 0]
    
    0 讨论(0)
  • 2021-01-22 03:00

    What you want is something like:

    def myindex(lst, target):
        for index, item in enumerate(lst):
            if item == target:
                return [index]
            if isinstance(item, (list, tuple)):
                path = myindex(item, target)
                if path:
                    return [index] + path
        return []
    

    Being recursive, this will deal with arbitrary depth of nesting (up to the recursion limit).

    For your example array, I get:

    >>> myindex(array, "a")
    [2, 2, 0]
    

    As Adam alludes to in the comments, explicitly checking instance types isn't very Pythonic. A duck-typed, "easier to ask for forgiveness than permission" alternative would be:

    def myindex(lst, target):
        for index, item in enumerate(lst):
            if item == target:
                return [index]
            if isinstance(item, str): # or 'basestring' in 2.x
                return []
            try:
                path = myindex(item, target)
            except TypeError:
                pass
            else:
                if path:
                    return [index] + path
        return []
    

    The specific handling of strings is necessary as even an empty string can be iterated over, causing endless recursion.

    0 讨论(0)
  • 2021-01-22 03:01

    I'm a bit late to the party, but I spent several minutes on it so I feel like it ought to be posted anyway :)

    def getindex(container, target, chain=None):
        if chain is None: chain = list()
        for idx, item in enumerate(container):
            if item == target:
                return chain + [idx]
            if isinstance(item, collections.Iterable) and not isinstance(item, str):
                # this should be ... not isinstance(item, basestring) in python2.x
                result = getindex(item, target, chain + [idx])
                if result:
                    return result
        return None
    
    0 讨论(0)
提交回复
热议问题