2010-04-23 6 views
1

J'ai un dictmeilleure façon de savoir le type

val_dict - {'val1': 'abcd', 'val': '1234', 'val3': '1234.00', 'val4': '1abcd 2gfff'} 

Toutes les valeurs à mes touches sont chaîne. Donc, ma question est comment trouver le type de mes valeurs dans le dict. Je veux dire que si je dis 'int' (val_dict ['val1']), cela me donnera une erreur.

En fait ce que je suis en train de faire est de savoir si la chaîne est une chaîne réelle ou int ou float.`

if int(val_dict['val1'): 
dosomething 
else if float(val_dict['val1']): 
dosomething 

grâce

+0

Je suppose qu'il importe réellement pour vous, que ce soit un int ou flotter? Les deux soutiennent les mêmes opérations de toute façon, bien qu'avec des précisions différentes bien sûr. – extraneon

+5

Pourquoi sont-ils des ficelles? Comment sont-ils entrés dans le dictionnaire en premier lieu? Pourquoi n'ont-ils pas été convertis en objets appropriés avant d'être mis dans le dictionnaire? –

+0

le code qui me donne le dict n'est pas dans ma main. Fondamentalement, je ne peux pas changer le dict. – laspal

Répondre

3

Peut-être ceci:

is_int = True 
try: 
    as_int = int (val_dict['val1']) 
except ValueError: 
    is_int = False 
    as_float = float (val_dict['val1']) 

if is_int: 
    ... 
else: 
    ... 

Vous pouvez se débarrasser de is_int, mais alors il y aura beaucoup de code (toute la gestion de la valeur flottante) dans try...except et je serais mal à l'aise à ce sujet.

+0

Aussi, faites attention au commentaire de S. Lott. Peut-être que vous n'avez même pas besoin de cela et que vous pouvez améliorer le dictionnaire. – doublep

-1

Une solution simple, si vous n'avez pas trop de formats, pourrait impliquer de vérifier le format de chaque valeur.

def intlike(value): 
    return value.isdigit() 
def floatlike(value): 
    import re 
    return re.match("^\d+\.\d+$") 

if intlike(val_dict['val1']): 
    dosomething(int(val_dict['val1'])) 
elif floatlike(val_dict['val1']): 
    somethingelse(float(val_dict['val1'])) 
else: 
    entirelydifferent() 

Cependant, il est vraiment plus facile d'utiliser le cadre d'exception de Python pour certains formats complexes:

def floatlike(value): 
    try: 
     float(value) 
    except ValueError: 
     result = False 
    else: 
     result = True 
    return result 
+0

Vous n'avez pas besoin d'utiliser une regex pour faire correspondre un flottant, et votre regex ne correspondra pas non plus à tous les flottants possibles. Python peut contraindre «0». et '.0' comme un flottant, alors que + est une correspondance pour "un ou plusieurs des précédents". – lunixbochs

+0

@lunixbochs: C'est pourquoi j'ai recommandé le framework d'exception à la place. Cependant, si les données proviennent d'une source connue, cette expression régulière peut très bien correspondre à des valeurs flottantes; il semble que le "+" soit correct sur le côté droit, par exemple. En outre, cela offre un moyen de vérifier les possibilités qui n'ont pas été explicitement demandées dans la question; par exemple, une autre regex pourrait identifier le '1abcd 2gfff' comme une liste. – eswald

2

Toutes les valeurs sont bien sûr « cordes réelles » (vous pouvez le faire avec eux, vous tous peut-être faire avec des chaînes!), mais je pense que la plupart des répondants savent ce que vous voulez dire - vous voulez essayer de convertir chaque valeur en plusieurs types possibles ('int' puis 'float' est spécifiquement ce que vous nommez, mais vous ne pouvez pas il y en a d'autres ...?) et retournez et utilisez la première conversion qui réussit.

Ceci est bien sûr le mieux encapsulé dans une fonction, loin de votre logique d'application. Si le meilleur match pour vos besoins est juste pour faire la conversion et le retour de la « meilleure valeur convertie » (et ils seront tous de la même occasion), puis:

def best_convert(s, types=(int, float)): 
    for t in types: 
    try: return t(s) 
    except ValueError: continue 
    return s 

si vous voulez faire quelque chose de différent dans chaque cas,:

def dispatch(s, defaultfun, typesandfuns): 
    for t, f in typesandfuns: 
    try: 
     v = t(s) 
    except ValueError: 
     continue 
    else: 
     return f(v) 
    return defaultfun(s) 

à appeler, par exemple, comme

r = dispatch(s, asstring, ((int, asint), (float, asfloat))) 

si les fonctions à appeler sur les « chaînes inconvertibles », les convertibles en int, et les convertibles à flotter, mais pas int , une respectivement asstring, asint, asfloat.

Je ne pas recommande de mettre la « structure » « essayez de le convertir à ces différents types, à son tour et agir en conséquence » code dans un mélange inextricable avec votre « logique de l'application » - c'est un cas clair pour la superposition d'une manière ordonnée la deux aspects, avec une bonne structure et une bonne séparation.

0

vous pouvez déterminer si la chaîne sera convertie en un int ou flotter très facilement, sans utiliser des exceptions

# string has nothing but digits, so it's an int 
if string.isdigit(): 
    int(string) 

# string has nothing but digits and one decimal point, so it's a float 
elif string.replace('.', '', 1).isdigit(): 
    float(string) 
Questions connexes