Take the 2-minute tour ×

I am facing very unusual problem, below is code inside a class where pitnamebasename is 2d list.
For example:=
pitnamebasename= [['a','b'],['n','m'],['b','c'],['m','f'],['c','d'],['d',''],['h','f']]
Above list is not necessary to be in any order like ['d',''] can be at 0th order.

Here is my function (inside a class):-

   def getRole(self,pitname):
            print '\n\n\nbasename=',basename
            while pitname and ind:
                    print 'basename=',basename
                    for i in self.pitnamebasename:
                            print 'comparing-',i[0],'and',pitname
                            if i[0] == pitname:
                                    print 'newpitname=',pitname
            print 'returning-',basename
            return basename

pitname is the string for example here it can be 'a'. I want return value to be 'd' mean the traversing must be like a to b, b to c and d to None, hence return value must be d. Please don't suggest me any other methods to solve.
Now my problem is that in the for loop its not looping till last but getting out in middle. Like return value is either b or c or even d depends on what I am searching. Actually list is very very long. Strange thing I noted that for loop loops only to that index where it loops till its first time. Like here first time for loop gets end when it find 'a' and pitname becomes 'b' but when it search for 'b' it loops till it find 'a' only. Does anyone knows how it is happening?

share|improve this question
pitnamebasename should probably be a dict. –  chepner Jun 11 at 14:40
@chepner agreed, O(1) lookup and much simpler/readable –  Paul Seeb Jun 11 at 14:41
The behavior you describe suggests that your version of pitnamebasename contains both an ['a', 'b'] value and a ['b', 'a'] value. This algorithm will go into an infinite loop in that case. It will only work if it's guaranteed that the list has no cycles like that. You should read about graph theory; pitnamebasename is a directed graph. –  senderle Jun 11 at 14:57
When I run your code it seems to work like expected for a, b, c, and d. They all return d. –  Hoopdady Jun 11 at 15:00
Hi @senderle, I found the problem, I thought that the inner loop is not getting completed and hence not getting my answer but actually there was a flaw in calling this function. I was adding new list in pitnamebasename and just after that I was calling this function mean adding and calling one after one was wrong. So the solution was to first fill the list completely and then call it to get desired result. So silly of me :( Thanks all for alternate solution and giving your time. –  Sagar Jun 13 at 6:12

2 Answers 2


First, change your '2d' array into a dict:

pitnamebasename = dict(pitnamebasename)

Now, it should be a simple matter of walking from element to element, using the value associated with the current key as the next key, until the value is the empty string; then return the current key. If pitname ever fails to exist as a key, it's treated as if it does exist and maps to the empty string.

def getRole(self, pitname):
    while pitnamebasename.get('pitname', '') != '':
        pitname = pitnamebasename[pitname]
    return pitname

A defaultdict could also be used in this case:

import collections.defaultdict
pitnamebasename = defaultdict(str, pitnamebasename)
def getRole(self, pitname):
    while pitnamebasename[pitname] != '':
        pitname = pitnamebasename[pitname]
    return pitname
share|improve this answer
Not that I don't approve the use of a dict, but at first glance I'm thinking OP's code should work, too. Also "You don't specify what the behavior should be if a value of pitname is not found as a key in the dictionary." - looks like the while loop will terminate since ind is never becoming true again. –  Ben Jun 11 at 14:48
True; I'll take that as the expected behavior and update my answer. –  chepner Jun 11 at 14:50
@Ben, you're right, a dict won't solve the problem here because this does exactly what the original code does. The problem is (probably) that the algorithm can't deal with the specific data passed to it. –  senderle Jun 11 at 15:01

You asked for the solution to your problem but I am having trouble replicating the problem. This code does the same thing without requiring you to change your entire class storage system.

By converting your list of lists into a dictionary lookup (looks like the following)

as_dict = dict(as_list_of_lists)
# as_dict = {'a': 'b', 'c': 'd', 'b': 'c', 'd': '', 'h': 'f', 'm': 'f', 'n': 'm'}

we can do a default dictionary lookup using the dictionary method .get. This will look for an item (say we pass it 'a') and return the associated value ('b'). If we look for something that isn't in the dictionary, .get will return the second value (a default value) which we can supply as ''. Hence as_dict.get('z','') will return ''

class this_class
    def __init__(self):

    def getRole(self,pitname):
        lookup = dict(self.pitnamebasename)
        new_pitname = pitname
        while new_pitname != '':
            pitname = new_pitname
            new_pitname = lookup.get(pitname, '')
        return pitname
share|improve this answer

Your Answer


