I want to find out the correct types of elements in a list in python. For example,
I am trying the previous code for now and I am unable to get the correct output.
list_of_elements = ['string', '23', '11.04', 'True']
types_list = {}
for x, i in enumerate(list_of_elements, 1):
if str(x):
types_list['id'] = i
types_list['type'] = 'String'
elif int(x):
types_list['id'] = i
types_list['type'] = 'Integer'
elif bool(x):
types_list['id'] = i
types_list['type'] = 'Boolean'
elif float(x):
types_list['id'] = i
types_list['type'] = 'Float'
print(types_list)
I want to get the result below:
output:
{
{id:1, type:'String'},
{id:2, type:'Integer'},
{id:3, type:'Float'},
{id:4, type:'Boolean'}
}
CodePudding user response:
The most robust way I know to interpret strings into types is to try each one and catch resulting ValueError
as they occur.
def text_to_value(text):
'''convert str to a float, int, bool or str'''
try:
# try to return an integer
return int(text)
except ValueError:
try:
# try to return a float instead
return float(text)
except ValueError:
# now try for a bool or plain text
return {'True': True, 'False': False}.get(text, text)
elements = ['string', '23', '11.04', 'True']
values = [text_to_value(text) for text in elements]
types = [type(value) for value in values]
Results:
types == [str, int, float, bool]
values == ['string', 23, 11.04, True]
Note: It's important to try int
before float
, since most valid int
literals will also validly parse to float
.
CodePudding user response:
Provided you reasonably trust1 the source of the strings in list_of_elements
, you can attempt to interpret the entries as Python literals using ast.literal_eval
:
import ast
list_of_elements = ['string', '23', '11.04', 'True']
types_list = []
for i, x in enumerate(list_of_elements, 1):
try:
parsed_x = ast.literal_eval(x)
except (ValueError, SyntaxError):
# Keep as str
parsed_x = x
types_list.append(
{
"id": i,
"type": type(parsed_x).__name__
}
)
print(types_list)
outputs
[{'id': 1, 'type': 'str'}, {'id': 2, 'type': 'int'}, {'id': 3, 'type': 'float'}, {'id': 4, 'type': 'bool'}]
Do note that this also opens the door to resolving strings to any Python literal type, not just str
s, float
s, int
s, and bool
s as requested. So, for example, the string '{1, 2, 3}'
will be reported as having the type set
, not str
.
1 Note that it is possible to crash the Python interpreter using maliciously crafted input to ast.literal_eval
. Do not pass it strings that you do not trust.
CodePudding user response:
try convert every string to a type, for example
for x in list_element:
try:
element = int(x)
except:
element = None # Cannot convert data to int, because is not a int
Use something like that for every type (int, float, bool) and the last type you should test have to be str, because all the data is string, so the element should be a string if not is int,float,bool.
CodePudding user response:
I have tried this one and got nearly my desired output but the answer 1 and answer 2 almost give my desired result. Some elements like 'NA', 'nan', and 'inf can cause some problems. These values should go to the other types except the 'String' data type. I think this could be optimized for my desired result
first_row_elements_in_csv_2 = ['drtger', '23', '55678', 'edrzt', 'True', 'False',
'234.67', '658969.89', '0', '1', 'NA']
first_row_elements_in_csv = ['Storm', 'folium', '29', '23020', '790', 'True']
def types_in_order(first_row_elements_in_csv_2):
types_promise = {}
types_id = {}
types = []
for i, x in enumerate(first_row_elements_in_csv_2,1):
if x == 'True' or x == 'False' or x == '0' or x == '1':
types_id = {}
types_id['id'] = i
types_id['type'] = 'Boolean'
types.append(types_id)
elif bool(re.match("^[0-9]", x)):
types_id = {}
types_id['id'] = i
types_id['type'] = 'Integer'
types.append(types_id)
elif str(x) and x != 'NA':
types_id = {}
types_id['id'] = i
types_id['type'] = 'String'
types.append(types_id)
else:
types_id = {}
types_id['id'] = i
types_id['type'] = 'Float'
types.append(types_id)
types_promise['data'] = types
return types_promise
print(types_in_order(first_row_elements_in_csv_2))
output:
{'data': [{'id': 1, 'type': 'String'},
{'id': 2, 'type': 'Integer'},
{'id': 3, 'type': 'Integer'},
{'id': 4, 'type': 'String'},
{'id': 5, 'type': 'Boolean'},
{'id': 6, 'type': 'Boolean'},
{'id': 7, 'type': 'Integer'},
{'id': 8, 'type': 'Integer'},
{'id': 9, 'type': 'Boolean'},
{'id': 10, 'type': 'Boolean'},
{'id': 11, 'type': 'Float'}]}