-1

I have following function in Python which should iterate over all text and return the words from index 0 to 5, from 1 to 6, from 2 to 7 and so on till the end of text. My function works well with print() statement, but when I use return instead of it, it works only till [0:5] then stops. Which keyword should I use without breaking loop ?

f1 = open("doc1.txt", 'r')
f1_words = f1.read().lower().split()

def iterate():
    for i in range(len(f1_words) - 4):
        for j in range(len(f1_words)+1):
            if(j-i==5):
                words1 = f1_words[i:j]
                return words1
            else:
                print(i, j)
print(iterate())
AMC
  • 2,642
  • 7
  • 13
  • 35
Bob Reynolds
  • 929
  • 3
  • 8
  • 21

4 Answers4

2

If you want to "return" from the function while keeping it alive, replace return with yield:

f1 = open("doc1.txt", 'r')
f1_words = f1.read().lower().split()

def iterate():
    for i in range(len(f1_words) - 4):
        for j in range(len(f1_words)+1):
            if(j-i==5):
                words1 = f1_words[i:j]
                yield words1
            else:
                print(i, j)

for words1 in iterate():
    print(words1)
jmd_dk
  • 12,125
  • 9
  • 63
  • 94
0

this will append all your "words" to a list then return the list

def iterate():
    wordLst = []
    for i in range(len(f1_words) - 4):
        for j in range(len(f1_words)+1):
            if(j-i==5):
                words1 = f1_words[i:j]
                wordLst.append(words1)
            else:
                print(i, j)
    return wordLst
print(iterate())
Ironkey
  • 2,568
  • 1
  • 8
  • 30
0

Return, as you figured out, returns something and stops the loop. If instead, you made an array of words that you add to instead of your return statement you can then return that at the end of your function.

def iterate():
    words_list=[]
    for i in range(len(f1_words) - 4):
        for j in range(len(f1_words)+1):
            if(j-i==5):
                words1 = f1_words[i:j]
                words_list+=[f1_words[i:j]]
            else:
                print(i, j)
    return(words_list)

print(iterate())
KJTHoward
  • 806
  • 4
  • 16
  • Instead of using `+=` with a list of length one, you can just write `words_list.append(...)`. – kaya3 Feb 25 '20 at 15:31
  • @kaya3 you can, but to me `+=` is quicker to type than `.append`. It's also a bit of personal preference, when I started teaching myself Python I used `+=` so it's just what I am used to I guess. – KJTHoward Feb 25 '20 at 15:40
  • @kaya3 didn't mention it, but I think using `+=` with a single element list like this sacrifices some readability, and is likely more error-prone. – AMC Feb 25 '20 at 16:00
  • As an example, if you forget to write the square brackets to make the list, `+=` with a string on the right-hand side will do the wrong thing and you'll have to figure out what the problem is. But mainly `append` is just more readable because it says in English what it's doing, and it also doesn't create an unnecessary extra list. – kaya3 Feb 25 '20 at 16:06
0

First, get rid of the second loop; you can compute the value of j instead of trying multiple possibilities.

With that out of the way, you have two options:

  1. accumulate values of words1 into a list to return at the end
  2. make your function a generator function which yields a value, then resumes when another value is requested.

Also, you should pass the string to iterate over as an argument; you might consider making the length of subwords an argument as well.

Option 1:

def iterate(s, n=5):
    return [s[i:i+n+1] for i in range(len(s) - n + 1)]

print(iterate(f1_words))

Option 2:

def iterate(s, n=5):
    for i in range(len(s) - n + 1):
        yield s[i:i+n+1]

print(list(iterate(f1_words)))
chepner
  • 497,756
  • 71
  • 530
  • 681