Friday, January 8, 2016

Python For Loop Fun

I had a problem recently where I needed to loop through a for loop to find some lines then only combine some lines so I thought for i in range(len(list)): ought to do it. It did not, I'm here to tell you the sad story of what happened. (Well actually this is a conversation I replied to with my buddy Phil, who should start a blog, cause he's awesome and probably could teach you many more things than I could).

Actually there is duplication but I think you forgot to include 'shut your dirty mouth' in the l array anyway... ;)
I added a "blah" to the 3rd element (0 based) so you can see when it's being printed vs the 2nd element.
Phils Function:


l = ['blah', 'blah blah', 'blah blah blah', 'blah blah blah blah']
for i in range(len(l)-1)):
   print l[i], l[i+1]

Phils Output
0blah blah blah
1
1blah blah blah blah blah
2
2blah blah blah blah blah blah blah
3
Tysons Function:


q = range(len(l)).__iter__()
for i in q:
   print l[i], l[i+1]
   q.next()

Tysons Output
0blah blah blah
2blah blah blah blah blah blah blah

Note the difference in the number of blahs and the number of lines
Phils approach prints current line plus next line through the entire list (and skips the last element due to the -1) Also note that even though we did a +=1 the next time through the loop the number is back is back....
Mine skip lines and print the current line and the next
Now this is obviously a contrived example as you can do range(0,len(l),2) and I think get the same result, but in my particular case I only wanted to combine certain lines, so only if line + 1 (or l[i+1] contained X would I want to print l[i] and l[i+1] afterwhich I wouldn't want to print the "new" l[i] (which was the same as the old i+1).
I hope that makes some more sense.
Here is a (only slightly) less contrived example.

My new function

l = ['one', 'my', 'buckle', 'my', 'shoe']

q = range(len(l)).__iter__()
for i in q:
    if 'my' in l[i]:
        if 'buckle' in l[i+1]:
            print str(i) + l[i], l[i+1]
            q.next()
        else:
            print l[i]
    else:
        print l[i]

My New Output
one
1my buckle
my
shoe

See now I only want to combine my buckle on the same line but not my shoe
So long story short, I can't just i+= 1 in my loop, I have to do a 'next()' but I can't just do that on an int (i.next() won't work in the above context) but I can do a next() on the range business (if it's got the iter, which I'm not sure about), however you need a variable to fiddle with to do that.


Anywho, next time you need to do the same thing as a simple c style for loop with numbers and want to increment remember.... it won't work like you expect it to.