49

I have a list of dictionaries as follows:

list = [ { 'a':'1' , 'b':'2' , 'c':'3' }, { 'd':'4' , 'e':'5' , 'f':'6' } ]

How do I convert the values of each dictionary inside the list to int/float?

So it becomes:

list = [ { 'a':1 , 'b':2 , 'c':3 }, { 'd':4 , 'e':5 , 'f':6 } ]
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
siva
  • 2,105
  • 4
  • 20
  • 37
  • 6
    It is very much discouraged to name variables as builtin types. Hopefully this is just for the purposes of the example, but if not you should avoid this in your code. – JoshAdel Mar 15 '11 at 19:30
  • Please fix your code from `list = [ { 'a':1 , 'b':2 , 'c':3 }}, { 'd':4 , 'e':5 , 'f':6 } ]` to `list = [ { 'a':1 , 'b':2 , 'c':3 }, { 'd':4 , 'e':5 , 'f':6 } ]` – Paolo Mar 15 '11 at 19:45
  • @Guandalino: Just wrote the codes on the spot.. sorry abt that. editted. – siva Mar 17 '11 at 19:27

8 Answers8

53

We have got to love list comprehensions.

[dict([a, int(x)] for a, x in b.items()) for b in list]

(Remark: for Python 2-only code, you may use "iteritems" instead of "items")

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Powertieke
  • 2,368
  • 1
  • 14
  • 21
  • 1
    pretty hard to digest though agreed impressive! How to deal with: ValueError: empty string for float() for floating and ValueError: invalid literal for int() with base 10: '0.6' for 'integering'? – siva Mar 17 '11 at 19:25
  • eventually i wud like to do stats on the list items. (max, min, average, stdev) – siva Mar 17 '11 at 19:34
  • You could write a function to replace the int() call in the comprehention to allow for all of the exeptions you desire. – Powertieke Mar 18 '11 at 07:43
  • Could be possible, but then i'd rather be using Perl :P – Powertieke Mar 18 '11 at 09:36
36
for sub in the_list:
    for key in sub:
        sub[key] = int(sub[key])

Gives it a casting as an int instead of as a string.

Jochen Ritzel
  • 104,512
  • 31
  • 200
  • 194
Jim
  • 3,236
  • 8
  • 33
  • 43
  • Haha, I was just changing that around, but yeah Jochen got it correctly, the whole naming your dictionary a list, confused me for a second. – Jim Mar 15 '11 at 19:21
7

If that's your exact format, you can go through the list and modify the dictionaries.

for item in list_of_dicts:
    for key, value in item.iteritems():
        try:
            item[key] = int(value)
        except ValueError:
            item[key] = float(value)

If you've got something more general, then you'll have to do some kind of recursive update on the dictionary. Check if the element is a dictionary, if it is, use the recursive update. If it's able to be converted into a float or int, convert it and modify the value in the dictionary. There isn't any built-in function for this and it can be quite ugly (and non-Pythonic since it usually requires calling isinstance).

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Jonathan Sternberg
  • 6,421
  • 7
  • 39
  • 58
2

For Python 3,

    for d in list:
        d.update((k, float(v)) for k, v in d.items())
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
emilpmp
  • 1,716
  • 17
  • 32
1
  newlist = []              # Make an empty list
  for i in list:            # Loop to hv a dict in list
     s = {}                 # Make an empty dict to store new dict data
     for k in i.keys():     # To get keys in the dict of the list
         s[k] = int(i[k])   # Change the values from string to int by int func
     newlist.append(s)      # To add the new dict with integer to the list
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
raton
  • 418
  • 5
  • 14
1

If you'd decide for a solution acting "in place" you could take a look at this one:

>>> d = [ { 'a':'1' , 'b':'2' , 'c':'3' }, { 'd':'4' , 'e':'5' , 'f':'6' } ]
>>> [dt.update({k: int(v)}) for dt in d for k, v in dt.iteritems()]
[None, None, None, None, None, None]
>>> d
[{'a': 1, 'c': 3, 'b': 2}, {'e': 5, 'd': 4, 'f': 6}]

Btw, key order is not preserved because that's the way standard dictionaries work, ie without the concept of order.

Paolo
  • 20,112
  • 21
  • 72
  • 113
1

To handle the possibility of int, float, and empty string values, I'd use a combination of a list comprehension, dictionary comprehension, along with conditional expressions, as shown:

dicts = [{'a': '1' , 'b': '' , 'c': '3.14159'},
         {'d': '4' , 'e': '5' , 'f': '6'}]

print [{k: int(v) if v and '.' not in v else float(v) if v else None
            for k, v in d.iteritems()}
               for d in dicts]

# [{'a': 1, 'c': 3.14159, 'b': None}, {'e': 5, 'd': 4, 'f': 6}]

However dictionary comprehensions weren't added to Python 2 until version 2.7. It can still be done in earlier versions as a single expression, but has to be written using the dict constructor like the following:

# for pre-Python 2.7

print [dict([k, int(v) if v and '.' not in v else float(v) if v else None]
            for k, v in d.iteritems())
                for d in dicts]

# [{'a': 1, 'c': 3.14159, 'b': None}, {'e': 5, 'd': 4, 'f': 6}]

Note that either way this creates a new dictionary of lists, instead of modifying the original one in-place (which would need to be done differently).

martineau
  • 119,623
  • 25
  • 170
  • 301
  • could I edit the "v" on the spot if v='' , i.e. empty items? would try and see. thanks. helpful. – siva Mar 18 '11 at 09:36
  • Regarding your question about handling empty "v" items: you could rewrite the `if` expression to deal with them as I've shown in my revised answer. – martineau Mar 18 '11 at 16:49
  • As to your second question about getting a syntax error at `... for k...`, dictionary comprehensions require Python 2.7+ or 3.1+, so using earlier versions could be causing the problem. – martineau Mar 18 '11 at 16:54
  • Follow up to my last comment: You could replace the `int(x)` in @Powertieke's answer with the conditional expression similar to what is in mine to get rid of the dictionary comprehension and result in something to use in earlier versions of Python. – martineau Mar 18 '11 at 17:07
1

A more general way using this number converter based on this answer.

def number(a, just_try=False):
    try:
        # First, we try to convert to integer.
        # (Note, that all integers can be interpreted 
        #  as float and hexadecimal numbers.)
        return int(a)
    except:
        # The order of the following conversions doesn't matter.
        # The integer conversion has failed because `a` 
        # contains hexadecimal digits [x,a-f] or a 
        # decimal point ['.'], but not both.
        try:
            return int(a, 16)
        except:
            try:
                return float(a)
            except:
                if just_try:
                    return a
                else:
                    raise


# The conversion:
[dict([a, number(x)] for a, x in b.items()) for b in list]

This will handle integer, float, and hexadecimal formats.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
betontalpfa
  • 3,454
  • 1
  • 33
  • 65