简体   繁体   中英

How to prepare a list containing a mix of integers, float and strings?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM