I've been working with some relatively complex arrays such as:
array = [ "1", 2, ["4", "5", ("a", "b")], ("c", "d")]
and I was looking for a way to find an item and retrieve is "index" (Is it OK to refer to the location of item such as "a" - that is inside a Tuple as index on the same level as array?)
Now my first thought was to use something like a simple helper function such as:
def myindex(nestedlist, item):
for i in nestedlist:
if item in i:
index = []
index.append(i)
index.append(i.index(item))
return index
But I'm sure you can guess that such a function won't do much good, especially since I don't know in advance how many levels the array might have, and what each level might contain (in terms of data type/structure)
Any hint in the right direction would be highly appreciate!
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.
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]
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
来源:https://stackoverflow.com/questions/24419487/find-index-of-nested-item-in-python