Say I have a data
data = 'A|B|2|D|0.3|5|kg|1.69|m'
I want to convert this into list using split('|'), but I get the list where all the values are converted to strings. I didn't see any similar problem on SE.
How can I get something like:
data_list = ['A','B',2,'D',0.3,5,'kg',1.69,'m']
where the type of the data are as they are (either int, str or float).
I don't want a very lengthy function but a shortest and simplest way to do it, is lambda possible (I am trying but no success so far)? , else something else is fine too.
any ideas.
Post edit:
I tried using lambda in following way:
da_list02 = map(lambda x: float(x) if type(float(x)) is float else str(x), da_list)
But, I am getting ValueError
. ValueError: could not convert string to float: A
Shouldn't the else
part of the lambda function
cover it? What's wrong with the lambda function
?
You can use nested try
and except
def convert(value):
try:
return int(value)
except ValueError:
try:
return float(value)
except ValueError:
return value
data = 'A|B|2|D|0.3|5|kg|1.69|m'
data_list = [convert(value) for value in data.split('|')]
print(data_list)
You can attempt to convert string to float.
data = 'A|B|2|D|0.3|5|kg|1.69|m'
def transform(x):
try:
return float(x)
except ValueError:
return x
[transform(x) for x in data.split('|')]
Output:
['A', 'B', 2.0, 'D', 0.3, 5.0, 'kg', 1.69, 'm']
You can try this:
import string
data = 'A|B|2|D|0.3|5|kg|1.69|m'
new_data = data.split("|")
final_list = []
for i in new_data:
if i[0] in string.ascii_uppercase or i[0] in string.ascii_lowercase:
final_list.append(i)
elif i.isdigit():
final_list.append(int(i))
else:
final_list.append(float(i))
Also, if you want a simple list comprehension, you can use this:
print [i if i[0] in string.ascii_lowercase or i[0] in string.ascii_uppercase else int(i) if i.isdigit() else float(i) for i in new_data]
Another way is to use regular expressions. Sorry I used a function.
import re
data = 'A|B|2|D|0.3|5|kg|1.69|m'
data_list = data.split('|')
print('data_list: ', data_list)
def parse(item):
if re.search("\d+\.\d+", item):
return float(item)
elif re.search("\d+", item):
return int(item)
else:
return str(item)
result = [parse(item) for item in data_list]
print('result: ', result)
for item in result:
print('{}, type: {}'.format(item, type(item)))
Here's my solution using regular expressions with anchors and map()
:
import re
data = 'A|B|2|D|0.3|5|kg|1.69|m'
def convert(item):
if re.match(r'-?\d+$', item):
return int(item)
elif re.match(r'-?\d+\.\d+$', item):
return float(item)
else:
return item
elements = map(convert, data.split('|'))
print(elements)
# ['A', 'B', 2, 'D', 0.3, 5, 'kg', 1.69, 'm']
Lambdas are not ideal for this situation because they are restricted to one liners. In this case you need a few conditionals.
You can have a short utility function that takes a string, inferes the type and returns the infered type. This solution will work with ints, floats and strings.
def set_type(s):
"""(str)->infered type.
Takes a string, inferes the type and returns either a string, int or float.
"""
if s.isnumeric():
return int(s)
if s.count(".") == 1 and "".join([c for c in s if c!="."]).isnumeric():
return float(s)
return s
Now the function can be mapped across a list:
>>> data = 'A|B|2|D|0.3|5|kg|1.69|m'
>>> lst = lst = data.split("|")
>>> list(map(set_type, lst))
['A', 'B', 2, 'D', 0.3, 5, 'kg', 1.69, 'm']
>>> data_list = list(map(set_type, lst))
>>> list(map(type, data_list))
[str, str, int, str, float, int, str, float, str]
Cheers.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.