almost a beginner
almost a beginner

Reputation: 1632

How can I create a loop for these if statements?

This is what I have achieved without a loop, which is ugly. I'm sure this can be done with a loop without having the repetitive statements:

def my_function(my_list_of_words):
    _digits = re.compile('\d')
    to_return = []

    for i, p in enumerate(my_list_of_words):
        new_list= []
        if 'start' in p:
            if bool(_digits.search(my_list_of_words[i+1])):
                new_list.append(p)
                new_list.append(my_list_of_words[i+1])
                if bool(_digits.search(my_list_of_words[i+2])):
                    new_list.append(my_list_of_words[i+2])
                    if bool(_digits.search(my_list_of_words[i+3])):
                        new_list.append(my_list_of_words[i+3])
                to_return.append(" ".join(new_list))

    return to_return

This works fine, but I don't know how many strings with numbers there will be after "start".

I want a loop that will continue looking for numbers in the list of strings, until the next index doesn't have a number.

I tried this:

def my_function(my_list_of_words):
    _digits = re.compile('\d')
    to_return = []

    for i, p in enumerate(my_list_of_words):
        new_list= []
        count = 1
        if 'start' in p:
            new_list.append(p)
            while bool(_digits.search(my_list_of_words[i+count])):
                new_list.append(my_list_of_words[i+count])
                ++count
            to_return.append(" ".join(new_list))

    return to_return

This doesn't work for some reason, it seems to loop for ever. I have also tried:

while True:
  if bool(_digits.search(my_list_of_words[i+count])):
    //doo things
    ++count
  else:
    break

This doesn't work for me either, it loops for ever.

Representation of what I'm trying to achieve:

['foo','foo','foo','start', '23', 'a32bc', '43', '332', 'foo', 'start', '23', 'a32bc']

would produce

['start 23 a32bc 43 332', 'start 23 a32bc']

Let's say we have the above list, when we reach 'start', I want to check whether the next has a number, in our case 23, if yes, then check the next for number (contains 32 so true again), keep doing this until the next doesn't have a number.

How can I achieve this with a loop?

Upvotes: 2

Views: 112

Answers (3)

ssr
ssr

Reputation: 1

Here, a simple program to find prime numbers in python which should cover your for loop in if condition :

def getPrime(X):
    print("The entered number is ",str(X))
    x=int(X)
    if x==1:
        print("1 is treated as speacial charater")
        return False
    for i in range(2,x):
        if x%i==0:
            print("{} is eual to {}x{}".format(x,i,x//i))
            return False
        else:
            print(x, "is a Prime Number")
            return True


print("Please enter number greater than 1 ")
M =input()
m=int(M)
for i in range(2,m):
    getPrime(i)

Upvotes: 0

Martijn Pieters
Martijn Pieters

Reputation: 1121494

The Pythonic version of a while True: count++ loop is an iterator, combined with next() function to advance to the next element. When the iterator is exhausted, a StopIteration exception is raised.

Create an iterator for your list (with the iter() function, then use nested loops to advance the iterator as you match:

def my_function(my_list_of_words, _digits=re.compile('\d').search):
    word_iter = iter(my_list_of_words)
    digit_words = None
    results = []
    try:
        curr = next(word_iter)
        while True:            
            # scan to the next 'start' value
            while 'start' not in curr:
                curr = next(word_iter)

            # collect digits; curr == start so we advance to the next
            digit_words = [curr]
            while True:
                curr = next(word_iter)
                if not _digits(curr):
                    break
                digit_words.append(curr)
            results.append(' '.join(digit_words))
            digit_words = []

    except StopIteration:
        # out of words, append remaining digit_words if there are any.
        if digit_words:
            results.append(' '.join(digit_words))

    return results

So this skips elements until 'start' is found, then collects entries that have digits, then switches back to finding 'start', etc. until StopIteration is raised by the next() call.

Demo:

>>> my_function(['foo','foo','foo','start', '23', 'a32bc', '43', '332', 'foo', 'start', '23', 'a32bc'])
['start 23 a32bc 43 332', 'start 23 a32bc']

You could replace all the results.append() calls with yield to make this a generator.

Note that I'm assuming there won't be any overlapping sequences; e.g. 'start' will never appear in a word with digits in a contiguous digits section.

Upvotes: 3

Faibbus
Faibbus

Reputation: 1133

import re

def my_function(my_list_of_words):
    _digits = re.compile('\d')
    to_return = []

    for i, p in enumerate(my_list_of_words):
        new_list= []
        if 'start' in p and i+1 < len(my_list_of_words):
            if bool(_digits.search(my_list_of_words[i+1])):
                new_list.append(p)
                for j in xrange(1,len(my_list_of_words)-i):
                    if bool(_digits.search(my_list_of_words[i+j])):
                        new_list.append(my_list_of_words[i+j])
                    else:
                        break
                to_return.append(" ".join(new_list))

    return to_return

print my_function(['foo','foo','foo','start', '23', 'a32bc', '43', '332', 'foo', "donotmatch66", 'start', '23', 'a32bc', 'start'])

will return

['start 23 a32bc 43 332', 'start 23 a32bc']

Upvotes: 1

Related Questions