Amrith Krishna
Amrith Krishna

Reputation: 2853

How to find indices of a given value in python multi list?

Given below is a sample multi list, that I am working with. Now I need to find the indices of a given value if it appears anywhere in the list. For eg: for lis[0][2][2][1][0] which is 'span 1 2', I would like to get the index as [0,2,2,1,0].

lis = [['Root', ['span 1 6'], ['Nucleus', ['span 1 3'], ['Nucleus', ['span 1 2'],  ['Nucleus', ['leaf 1'],  ['text',  "Specific knowledge "]], ['Satellite', ['leaf 2'], ['rel2par Elaboration'], ['text', 'required !_']]], ['Satellite', ['leaf 3'], ['rel2par Elaboration'], ['text', 'The tester is ']]], ['Satellite', ['span 4 6'], ['rel2par Elaboration'], ['Satellite', ['leaf 4'], ['rel2par Attribution'], ['text', 'For instance , the tester is aware!_']], ['Nucleus', ['span 5 6'],  ['Nucleus', ['leaf 5'], ['rel2par Contrast'], ['text', 'that a!_']], ['Nucleus', ['leaf 6'], ['rel2par Contrast'], ['text', 'but ']]]]]]

I tried the following (modified from a web source).

from copy import copy
def scope2(word, list, indexes = None):
    flag = 0
    result = []
    if not indexes:
        indexes = []
    for index, item in enumerate(list):
        try:
            current_index = indexes + [index]
            result.append(current_index + [item.index(word)])
        except ValueError:
            pass
        print item
        print str(current_index) + ":::::" + str(list.index(item))
        for stuff in item:        
            if type(stuff) == type([]):
                flag =1 

    if flag==1:
        indexes.append(index)
        result.extend(scope2(word, item, copy(indexes)))

return result

Here the problem is that the index of sibling (lists at same level) also gets returned, but not always. Some sample outputs are like

for 0,2,3,1 it returns 0,2,3,1,0, similarly for lis[0][2][3][4][3][3] it returns 0,2,3,3,4,3,3 and so on. What can be the possible problem?

Upvotes: 0

Views: 172

Answers (2)

MattH
MattH

Reputation: 38247

Here's an implementation of depth first and breadth first searching, not limited to strings. Would require a little reworking to search for a list or a tuple.

>>> l = [['Root', ['span 1 6'], ['Nucleus', ['span 1 3'], ['Nucleus', ['span 1 2'],  ['Nucleus', ['leaf 1'],  ['text',  "Specific knowledge "]], ['Satellite', ['leaf 2'], ['rel2par Elaboration'], ['text', 'required !_']]], ['Satellite', ['leaf 3'], ['rel2par Elaboration'], ['text', 'The tester is ']]], ['Satellite', ['span 4 6'], ['rel2par Elaboration'], ['Satellite', ['leaf 4'], ['rel2par Attribution'], ['text', 'For instance , the tester is aware!_']], ['Nucleus', ['span 5 6'],  ['Nucleus', ['leaf 5'], ['rel2par Contrast'], ['text', 'that a!_']], ['Nucleus', ['leaf 6'], ['rel2par Contrast'], ['text', 'but ']]]]]]
>>> def depth_first(term,data):
...   for i, item in enumerate(data):
...     if isinstance(item,Sequence) and not isinstance(item,basestring):
...       r = depth_first(term,item)
...       if not r is None:
...         return [i] + r
...     else:
...       if item == term:
...         return [i]
...
>>> def breadth_first(term,data):
...   later = []
...   for i, item in enumerate(data):
...     if isinstance(item,Sequence) and not isinstance(item,basestring):
...       later.append((i,item))
...     else:
...       if item == term:
...         return [i]
...   for i, item in later:
...     r = breadth_first(term,item)
...     if not r is None:
...       return [i] + r
>>> depth_first('span 1 2',l)
[0, 2, 2, 1, 0]
>>> breadth_first('span 1 2',l)
[0, 2, 2, 1, 0]

Upvotes: 1

falsetru
falsetru

Reputation: 368904

>>> def trail(word, lst):
...     if word in lst:
...         return [lst.index(word)]
...     for i, x in enumerate(lst):
...         if not isinstance(x, list):
...             continue
...         ret = trail(word, x)
...         if ret is not None:
...             return [i] + ret
... 
>>> trail('span 1 2', lis)
[0, 2, 2, 1, 0]
>>> lis[0][2][2][1][0]
'span 1 2'
>>> trail('no such string', lis)
>>> 

Upvotes: 2

Related Questions