1

Im a beginner in python so forgive me if the answer is comical :)

I'm trying to write some code that coverts str into int and floats. I will give an example below:

if we are given this:

data = [['ab2'], ['-123'], ['BIKES', '3.2'], ['3.0', '+4', '-5.0']]

we need to return this:

data = [['ab2'], [-123], ['BIKES', 3.2], [3, 4, -5]]

I have tried in several ways to do this like so:

# first attempt
for sublist in data:
        for value in range(0, len(sublist)): 
            if "." in sublist[value]:
                sublist[value] = float(sublist[value])
            elif sublist[value].isnumeric():
                sublist[value] = int(sublist[value])
# second attempt
for sublist in data:
    for value in sublist:
        if value.isnumeric():
            if int(value) == float(value):
                value = int(value)
            else:
                value = float(value)

I keep coming back to the same few problems though:

  1. the isnumeric or isdigit doesn't accept "-", "+" or "." in the answer, so if i have "-123.4" thats not a number
  2. Numbers like 3.0 or 4.0, need to be converted into integers and not floats
  3. I need a way to mutate the original list and basically "replace' the old numbers, with new

I know you can use try/except blocks but i haven't studied those and I don't understand them, so if anyone could give me some guidance on what to do, or how to alter my code, it would be greatly appreciated :)

Thanks

  • Is this an assignment? Are you not allowed to use try except? – Yoshikage Kira Mar 11 '22 at 05:40
  • @Goion Its a project of sorts and we are "limited" to what we have learned, since its being marked. if I use try/expect and I don't even know what it does, then not only am I plagiarizing, I also don't know what it does –  Mar 11 '22 at 06:05

5 Answers5

1

The easiest solution is to use a try-except block. After all, it's easier to ask forgiveness than permission. With a try-except, as soon as an error is encountered in the try block, control moves to the except block.

In the example below, if float(value) fails, a ValueError is raised. This error means the except ValueError: block will be executed. Since we just want to ignore the error, we pass in the except block.

If no error is raised, execution continues on to the next statement (if float_value...) and the except block is skipped.

for sublist in data:
    for index in range(len(sublist)): 
        value = sublist[index]
        
        try:
            float_value = float(value)             # Convert to float
            if float_value.is_integer():           # If successful, check if it's an integer
                sublist[index] = int(float_value)  # If integer, convert to integer and save the integer value
            else:
                sublist[index] = float_value       # If not, save the float
            continue                               # Skip the rest of the loop
        except ValueError:                         # Catch ValueError if float() fails
            pass                                   # Do nothing if error
         

Which gives:

data = [['ab2'], [-123], ['BIKES', 3.2], [3, 4, -5]]

If you have large integers, you can try to convert it to an int before you convert it to a float, because as Kelly mentioned in their comment, floats lose precision for large ints:

    for index in range(len(sublist)):
        value = sublist[index]
        try:
            int_value = int(value)      # Convert to int
            sublist[index] = int_value  # If successful, save
            continue                    # Skip the rest of the loop
        except ValueError:              # Catch the ValueError if int() fails
            pass  

        # And then the try block for floats
Pranav Hosangadi
  • 23,755
  • 7
  • 44
  • 70
1

Using a nested try/except:

def to_num(s):
    # remove trailing ".0"
    x = s.rstrip('0').rstrip('.') if '.' in s else s
    try: # attempt int conversion
        return int(x)
    except ValueError:
        try: # attempt float conversion
            return float(x)
        except ValueError:
            return s   # if all failed return input

[[to_num(x) for x in l] for l in data]

Output:

[['ab2'], [-123], ['BIKES', 3.2], [3, 4, -5]]
mozway
  • 194,879
  • 13
  • 39
  • 75
1

This uses a regex to find valid numbers. Like most such filters, this creates a new list with the desired values instead of writing in place.

import re

nums = r"[+-]?[\d.]+"

data = [['ab2'], ['-123'], ['BIKES', '3.2'], ['3.0', '+4', '-5.0']]

newlist = []
for sublist in data:
    newsub = []
    for value in sublist:
        if re.match( nums, value ):
            if '.' not in value:
                newsub.append( int(value) )
            else:
                value = value.rstrip('0').rstrip('.')
                if '.' not in value:
                    newsub.append( int(value) )
                else:
                    newsub.append( float(value) )
        else:
            newsub.append( value )
    newlist.append( newsub )

print(newlist)
Tim Roberts
  • 48,973
  • 4
  • 21
  • 30
  • It seems like this might not work with ‘malformed floats’ like 1.1.1.1, which, if present, should probably be kept a string rather than giving an exception, right? – kcsquared Mar 11 '22 at 05:49
  • True, but the OP hasn't provided much of a spec. ;) `value.count('.')` might be the most expedient way to handle that. The regex gets a little complicated. – Tim Roberts Mar 11 '22 at 06:03
0
# Assuming data only contains list and in the list elements can also be list

data = [['ab2'], ['-123'], ['BIKES', '3.2'], ['3.0', '+4', '-5.0']]


def checkPureInt(n):
    n_str = str(n)
    if n_str[-1] == '0' and n_str[-2] == ".":
        return True
    else:
        return False


for i in range(len(data)):
    if type(data[i]) == list:

        for j in range(len(data[i])):
            try:
                data[i][j] = float(data[i][j])
                if checkPureInt(data[i][j]):
                    data[i][j] = int(data[i][j])
            except:
                pass

print(data)
  • 2
    1. Not a good idea to have a bare silent `except`, since it will catch all errors (that come from possible bugs) and even some keyboard interrupts. 2. `isinstance(data[i], list)` is better than `type(data[i]) == list` 3. Your `checkPureInt()` fails on e.g. `1.00` – Pranav Hosangadi Mar 11 '22 at 05:49
  • @PranavHosangadi we are not doing anything if str caught. Yes we can also use isinstance, but what problem if we are using type(data[i]) == list? Thanks :) – Gautam Jangid Mar 11 '22 at 05:55
  • `isinstance` works with inheritance. `type() == ` doesn't. – Pranav Hosangadi Mar 11 '22 at 05:56
  • @PranavHosangadi 3. The function checkPureInt taking int or float in the parameter. I think it is fine. As the problem we need only to check the element is list or not , that's why just using type, list is inbuilt in python so I thought its fine with this question. What you think ? – Gautam Jangid Mar 11 '22 at 06:17
  • Okay, I didn't realize that `checkPureInt()` takes a float. fyi, you can also use `float.is_integer()`. As for the `type` point: https://stackoverflow.com/questions/1549801/what-are-the-differences-between-type-and-isinstance – Pranav Hosangadi Mar 11 '22 at 16:07
  • @PranavHosangadi Great!, Thanks for sharing this useful information :) – Gautam Jangid Mar 12 '22 at 04:31
-1

import math
def is_number(string):
    try:
        float(string)
        return True
    except ValueError:
        return False
data=[['ab2'], ['-123'], ['BIKES', '3.2'], ['3.0', '+4', '-5.0']]
for i in range(len(data)):
    for j in range(len(data[i])):
        value=data[i][j]
        if is_number(value):
            if int(float(value)) == float(value):
                data[i][j] = int(float(value))
                #print(value)
            else:
                data[i][j] = float(value)
                #print(value)
print(data)
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Mar 11 '22 at 07:30