E.hu
E.hu

Reputation: 7

For loops that include range in python3

I need to define a function receives a string that is made of numbers and checks the following requirement:

  1. the string isnt empty
  2. the first character is in range (1,10)
  3. every character besides the first is in range (0,10) if the string answers all the requirements return True, else return False.

What ive tried is if in for loops and vice versa.

I've also tried moving the return function in the following code to different indentations which didn't help

def is_positive_int(st):
n = len(st)
if n > 0:
    if st[0]>= 0 and st[0]<= 9:
        for i in range(1,n):
            if st[i]>= 0 and st[i]<= 9
        return True

I've also tried:

def is_positive_int(st):
n = len(st)
for n > 0:
    if st[0] >= 1 and st[0]<=9:
        for i in range (1,n):
            if st[i]>=1 and st[i]<= 9
        return True
    else:
        return False

which returns: invalid syntax for n > 0 (I'm not sure why)

For example:

print(is_positive_int("123")) 
should return True

Where as

print(is_positive_int("123.0")) 
should return False

And

print(is_positive_int("0")) 
should return False

Upvotes: 0

Views: 1614

Answers (8)

Guy
Guy

Reputation: 647

Using the builtin function all() and a list comprehension, just to add to the many options.

def test_num(num):
    # check for empty string
    if len(num) == 0:
        return False
    # check all numbers are digits,
    # if so, is the first digit > 0
    return all(i.isdigit() for i in num) and int(num[0]) > 0



if __name__ == '__main__':
    for num in ['', '0', '1', '123.0', '123', '+123', '-123']:
        print(f'\'{num}\' is positive: {test_num(num)}')

# '' is positive: False
# '0' is positive: False
# '1' is positive: True
# '123.0' is positive: False
# '123' is positive: True
# '+123' is positive: False
# '-123' is positive: False

Upvotes: 0

Devesh Kumar Singh
Devesh Kumar Singh

Reputation: 20500

You can use the str.isdigit function to check if a string is a digit between 0 and 9, and we can utilize it here as follows.

def is_positive_int(st):
    #Get the length of the string
    n = len(st)
    #Flag to capture result
    result = True
    #If the string is empty, result is False
    if n == 0:
        result = False
    #If the string has only one character, if the character is not 0, result is False
    elif n == 1:
        if st[0] == '0':
            result =  False
    else:
        #Otherwise iterate through all characters in the string
        for i in range(1, n):
            #If we find a character which is not a digit, result is False
            if not st[i].isdigit():
                result = False
                break
    #Return the final result
    return result

The outputs for the function above then will be

print(is_positive_int(""))
#False
print(is_positive_int("0"))
#False
print(is_positive_int("1"))
#True
print((is_positive_int("123.0")))
#False
print((is_positive_int("123")))
#True

Upvotes: 0

Shijith
Shijith

Reputation: 4882

if you have to check only for positive integers you can use .is.isdigit

def is_positive_int(st):
    return st.isdigit() and int(st) > 0

>>>is_positive_int('123')
True
>>>is_positive_int('123.0')
False
>>>is_positive_int('0')
False
>>>is_positive_int('#$%')
False
>>>is_positive_int('-123')
False
>>>is_positive_int('')
False

Upvotes: 0

warped
warped

Reputation: 9481

You need to convert the entries in your string to int, otherwise your conditional statements will throw an error:

your code:

def is_positive_int(st):
    n = len(st)
    if n > 0:
        if (st[0]>= 0) and (st[0]<= 9):
            for i in range(1,n):
                if st[i]>= 0 and st[i]<= 9:
                    return True

Should throw an error. At least it does when I run it on '123'

TypeError: '>=' not supported between instances of 'str' and 'int'

So, you could change to:

def is_positive_int(st):
    n = len(st)
    if n > 0:
        if (int(st[0])>= 0) and (int(st[0])<= 9):
            for i in range(1,n):
                if int(st[i])>= 0 and int(st[i])<= 9:
                    return True

Since nowhere in this function it is asserted if there are non-digit characters, it cannot return False when encountering those. Contrary, it will throw an error, when it tries the conversion. So you could do:

def is_positive_int(st):
    entries = list(st)              # create a list of all items in the string
    if entries:                     # assert this list has length > 0
        output = True               # initialise output
        for e in entries:           
            output *= e.isdigit()   # update outputs : a single False will convert output to 0.
        return bool(output)         # convert output to boolean
    else:                           # if the string is empty, return False. 
        return False

Upvotes: 0

Lucas
Lucas

Reputation: 395

You can also just iterate over the string:

for character in st:
    # your conditionals 

Then use character in place of st[i]

But also note, that with the conditionals you can not compare a string with a number. So what you should do is either make a set of the digits or use the isdigit() method for strings. Taking it all together your function should be something like this:

def is_positive_int(st):
   if not (st and st[0] != '0'):
       return False

   for character in st:
       if not character.isdigit():
           return False

   return True

Upvotes: 1

theberzi
theberzi

Reputation: 2695

Use range(len(iterable)) to iterate over the indexes of an iterable:

def is_positive_int(string):
    positive_ints = {1, 2, 3, 4, 5, 6, 7, 8, 9}

    if len(string) == 0:
        return False
    if int(string[0]) not in positive_ints:
        return False

    for i in range(1, len(string)):
        if int(string[i]) not in (positive_ints | {0}):
            return False

    return True

Note the use of sets to define accepted numbers, since it's an efficient data structure for this purpose, and could also be constructed dynamically with positive_ints = set(range(1,10)).

The int() calls are there because the elements of the string (string[i]) will be strings, and would always compare to false since 1 == "1" is False.

Lastly, the cascading style of returns is often preferred as it skips parts of the function that won't be relevant and only returns True if nothing else stops it until the end.

Instead of operating on indexes, you can iterate on the characters of the string themselves:

def is_positive_int(string):
    positive_ints = set(range(1, 10))

    if len(string) == 0:
        return False
    if int(string[0]) not in positive_ints:
        return False

    for character in string:
        if int(character) not in (positive_ints | {0}):
            return False

    return True

Note that both of these will raise an exception if a character in the string cannot be converted to int. This can be prevented by converting the numbers to string instead:

def is_positive_int(string):
    positive_ints = set(str(x) for x in range(1, 10))

    if len(string) == 0:
        return False
    if string[0] not in positive_ints:
        return False

    for i in range(1, len(string)):
        if string[i] not in (positive_ints | {"0"}):
            return False

    return True

Upvotes: 0

Nic Wanavit
Nic Wanavit

Reputation: 2703

Try this If you input something that isnt a string that can convert to int, it will run the except condition. len(input)>1 just confirms that there is a second digit

def is_positive_int(input):
    try:
        if int(input[0]) in range(1,10) and int(input) and len(input)>1:
            return True
        else:
            return False
    except:
        print('invalid input')

Upvotes: 0

Ralf
Ralf

Reputation: 16515

I can suggest 2 alternative approaches:

Option 1: iterate directly over the string and compare each char to allowed chars for each position (do not compare chars to numbers).

import string

def func(input_str):
    if len(input_str) == 0:
        return False

    for i, c in enumerate(input_str):
        if i == 0:
            allowed_chars = string.digits[1:]       # exclude '0'
        else:
            allowed_chars = string.digits

        if c not in allowed_chars:
            return False

    return True

Option 2: use regular expressions; I know that they aren't always a solution, but in this case they allow for a really short code solution.

import re

def func(input_str):
    if re.match(r'^[1-9][0-9]*$', input_str):
        return True

    return False

Does this help?

Upvotes: 0

Related Questions