1

I have written a bisect function that takes a word list "t" and a word "val". It recursively halves the list until the index of the list is the word or returns false. If it finds the word, it is supposed to return it.

I have read multiple books, the documentation, and all the applicable questions here on SO but I still cannot determine what I am doing wrong: why won't the function return the value? It will print the value just fine, but no return except None.

Any help is greatly appreciated!

def bisect(t, val):
    if t[len(t)/2] < val and len(t) > 1:
        t = t[len(t)/2:]
        bisect(t, val)
    elif t[len(t)/2] > val and len(t) > 1:
        t = t[:len(t)/2]
        bisect(t, val)
    elif t[len(t)/2] == val:
        t = t[len(t)/2]
        #print type(t), t
        return t
    else:
        return False

b = make_list(t)
x = bisect(b, 'and')
print x
2
  • Are you sure you don't want to return bisect(..) when performing the recursive calls? Commented Dec 11, 2015 at 2:20
  • If I put a print statement after if and the first elif, it prints the (half) list correctly until it finds the value. Am I understanding your question correctly? Commented Dec 11, 2015 at 2:32

2 Answers 2

1

The main issue here is that you need to return t from each call to the recursively called function. Picture the call stack using my modified code below:

def main():
    b = ['a', 'able', 'ability', 'abort', 'and', 'arc', 'zygote']
    x = bisect(b, 'and')
    print x



def bisect(t, val):
    if t[len(t)/2] < val and len(t) > 1:
        t = t[len(t)/2:]
        t = bisect(t, val)
    elif t[len(t)/2] > val and len(t) > 1:
        t = t[:len(t)/2]
        t = bisect(t, val)
    elif t[len(t)/2] == val:
        t = t[len(t)/2]
        print type(t), t
    else:
        return False

    return t

if __name__ == '__main__':
    main()

The first time bisect is called, t is set to ['abort', 'and', 'arc', 'zygote']. On the second call to bisect, t is set to ['abort', 'and'] On the third call, we have 'and' located, and return that value.

IF you returned as you had (only returning from the exact match or False result), then you return to the second call (['abort', 'and']), then the first call (['abort', 'and', 'arc', 'zygote']), and finally you return without hitting a return t in that first call. Thus, nothing is returned.

Rewriting your original code as I have, everything is the same until we find the match. However, with my code, the final call returns t back into the t variable used in the second call. That returns the value to the first call, which returns the result back to the calling code.

Hopefully, that clears up your question.

Sign up to request clarification or add additional context in comments.

1 Comment

There is one trivial case. If your original example had the target word in the exact middle of the list, then it would return the match correctly.
0

This modified version works:

def bisect(t, val):
    mid = len(t)//2
    mid_ele = t[mid]
    end = len(t)
    if mid_ele < val and end > 1:
        t = t[mid:]
        return bisect(t, val)
    elif mid_ele > val and end > 1:
        t = t[:mid]
        return bisect(t, val)
    elif mid_ele == val:
        t = mid_ele
        return t
    else:
        return False

b = ['she', 'he', 'you', 'and', 'me']
print(bisect(b, 'and'))

prints the desired:

and

I made it Python 3 proof using // for integer division and added two returnsbefore the recursive call.

1 Comment

Understood. And my apologies: the b = make_list(t) calls this: t = open('list.txt') def make_list(t): a = [] for line in t: word = line.strip() a.append(word) return a The list prints fine when b is called.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.