Reputation: 777
I got a list of strings from an REST API. I know from the documentation that the item at index 0 and 2 are integers and item at 1 and 3 are floats.
To do any sort of computation with the data I need to cast it to the proper type. While it's possible to cast the values each time they're used I rather prefer to cast the list to correct type before starting the computations to keep the equations cleaner. The code below is working but is very ugly:
rest_response = ['23', '1.45', '1', '1.54']
first_int = int(rest_response[0])
first_float = float(rest_response[1])
second_int = int(rest_response[2])
second_float = float(rest_response[3])
As I'm working with integers and floats in this particular example one possible solution is to cast each item to float. float_response = map(float, rest_response)
. Then I can simply unpack the list to name the values accordingly in the equations.
first_int, first_float, second_int, second_float = float_response
That is my current solution (but with better names) but while figuring that one out I became curious if there's any good pythonic solution to this kind of problem?
Upvotes: 6
Views: 670
Reputation: 109
Of all of the solutions offered, the one you provide in your question is the best. It has speed and clarity.
If you wanted to shorten the solution you provided, you could shorten it to one line:
first, second, third, fourth = int(lst[0]), float(lst[1]), int(lst[2]), float(lst[3])
I don't know all of the possible formats to the incoming data, but if the float values will always have a decimal, then another solution would be:
first, second, third, fourth = [float(i) if '.' in i else int(i) for i in rest_response]
Upvotes: 0
Reputation: 2180
yep, given that all are strings, just write a regex that checks, if the string has a '.' in it and if yes, cast it to float. Otherwise to int
edit: regex is redundant, simple in string
is sufficient.
here is what I would do:
import re
def convert_type(item):
if re.match('^[^.]*$', item):
item = int(item)
else:
item = float(item)
return item
Simpler function:
def convert_type(item):
if '.' in item:
return float(item)
else:
return int(item)
what = convert_type('2')
print(what, type(what))
convert_this = ['21.44', '12']
converted_list = list(map(convert_type, convert_this))
list(map(type, converted_list))
But I'm happy to hear simpler and more straightforward solution
Upvotes: 0
Reputation: 38809
The existing answer is perfect if you know the types you expect to be given. If however you don't know beforehand if your values are int or floats, then you can use the AST module to parse the string safely into the appropriate type:
import ast
Then, you call:
numbers = [ast.literal_eval(s) for s in strings]
Upvotes: 2
Reputation: 103824
If your list is in that pattern of every other, you can use modulo:
>>> [int(x) if i % 2==0 else float(x) for i,x in enumerate(rest_response)]
[23, 1.45, 1, 1.54]
Or, if you want to take advantage of tuple assignment to named variables, you can slice and map by desired type:
first_int, second_int=map(int, rest_response[0::2])
first_float, second_float=map(float, rest_response[1::2])
Upvotes: 1
Reputation: 13206
I think it is reasonably Pythonic to try to convert to an int, if this fails then use a float,
rest_response = ['23', '1.45', '1', '1.54']
float_response = []
for r in rest_response:
try:
float_response.append(int(r))
except ValueError:
float_response.append(float(r))
Upvotes: 0
Reputation: 46849
this is a solution using itertools.cycle
in order to cycle through the cast functions:
from itertools import cycle
first_int, first_float, second_int, second_float = [cast(f)
for f, cast in zip(rest_response, cycle((int, float)))]
Upvotes: 6
Reputation: 5609
Define a second list that matches your type casts, zip it with your list of values.
rest_response = ['23', '1.45', '1', '1,54']
casts = [int, float, int, float]
results = [cast(val) for cast, val in zip(casts, rest_response)]
Upvotes: 17