Cuando se me da una lista de datos, se me pide que convierta las cadenas dentro de la lista a un tipo correspondiente, como int si la cadena contiene un número entero o un flotante si no contiene un número entero. Pero me encuentro con este problema donde convertirá el valor pero no cambia el valor original en la lista.

Por ejemplo, si se da:

d = [['abc', '123', '45.6', 'True', 'False']]

Se supone que debe verse así después de la conversión:

[['abc', 123, 45.6, True, False]]

Hasta ahora he intentado escribir un bucle for y convertir los valores de esa manera, pero como mencioné, no cambia la lista original:

for lst in data:
    for index in lst:
        if index.isdigit():
            index = int(index)
        elif not index.isdigit():
            index = float(index)

No estoy realmente seguro de cómo solucionar el problema o si hay otra forma de solucionarlo. ¡Cualquier ayuda sería apreciada! Gracias :)

4
KC29 29 oct. 2017 a las 22:21

3 respuestas

La mejor respuesta

Debe actualizar los elementos en los índices iniciales utilizando la suscripción a la lista, es decir, asignar a cada índice después de transmitir el elemento. Puede hacerlo utilizando enumerate que suministra cada elemento en la lista con un índice correspondiente:

import ast

d = [['abc', '123', '45.6', 'True', 'False']]

for lst in d:
  for i, x in enumerate(lst):
    try:
        lst[i] = ast.literal_eval(x)
    except (ValueError, SyntaxError):
        lst[i] = x
print(d)
# [['abc', 123, 45.6, True, False]]

ast.literal_eval intenta analizar cada elemento de cadena como un literal de Python, si eso falla (con error), vuelva al elemento original (consulte EAFP).

Si tiene una gran cantidad de estas cadenas, sería más rápido (aunque con un código menos limpio y probablemente propenso a errores) escribir su propio analizador, sin embargo, probablemente sea mejor dejar que ast.literal_eval haga todo el trabajo sucio.

5
Moses Koledoye 29 oct. 2017 a las 20:29

Pruebe esto (no se necesita biblioteca):

data = [['abc', '123', '45.6', 'True', 'False']]


def isfloat(x):
    try:
        a = float(x)
    except ValueError:
        return False
    else:
        return True


def isint(x):
    try:
        a = float(x)
        b = int(a)
    except ValueError:
        return False
    else:
        return a == b


for counter1, box in enumerate(data):

    for counter2, items in enumerate(box):

        if isfloat(items) is True:
            data[counter1][counter2] = float(items)

        elif isint(items) is True:
            data[counter1][counter2] = float(items)

        elif items == "True":
            data[counter1][counter2] = True

        elif items == "False":
            data[counter1][counter2] = False

        else:
            pass

print(data)
0
DRPK 29 oct. 2017 a las 19:34

Aquí sin ninguna biblioteca. Solo corta las cosas y algunos trucos de prueba, excepto. isdigit() comprueba si string es digit, si no lo es, significa que es float. Para True y False, solo verifica si están en la lista.

Esto se puede hacer más corto, solo lo hice de esta manera para que pueda ver cómo funciona.

all = [['abc', '123', '45.6', 'True', 'False']]

for d in all:
    for x,y in enumerate(d):
        if y == "True":
            d[x] = True
        if y == "False":
            d[x] = False

for d in all:
    for x,y in enumerate(d):
        try:
            if y.isdigit() == True:
                d[x] = int(y)
            else:
                d[x] = float(y)
        except:
            pass

Salida;

['abc', 123, 45.6, True, False]

abc
<class 'str'>
123
<class 'int'>
45.6
<class 'float'>
True
<class 'bool'>
False
<class 'bool'>
1
GLHF 29 oct. 2017 a las 21:08