4

I would like to take a python dictionary of lists, convert the lists to numpy arrays, and restore them in the dictionary using list comprehension.

For example, if I had a dictionary

myDict = {'A':[1,2,3,4], 'B':[5,6,7,8], 'C':'str', 'D':'str'}

I wish to convert the lists under keys A and B to numpy arrays, but leave the other parts of the dictionary untouched. Resulting in

myDict = {'A':array[1,2,3,4], 'B':array[5,6,7,8], 'C':'str', 'D':'str'}

I can do this with a for loop:

import numpy as np

for key in myDict:
    if key not in ('C', 'D'):
        myDict[key] = np.array(myDict[key])

But is it possible to do this with list comprehension? Something like

[myDict[key] = np.array(myDict[key]) for key in myDict if key not in ('C', 'D')]

Or indeed what is the fastest most efficient way to achieve this for a large dictionaries of long lists. Thanks, labjunky

labjunky
  • 831
  • 1
  • 13
  • 22

3 Answers3

3

With Python 2.7 and above, you can use a dictionary comprehension:

myDict = {'A':[1,2,3,4], 'B':[5,6,7,8], 'C':'str', 'D':'str'}
myDict = {key:np.array(val) if key not in {'C', 'D'} else val for key, val in myDict.iteritems()}

If you're below version 2.7 (and hence don't have dictionary comprehensions), you can do:

myDict = {'A':[1,2,3,4], 'B':[5,6,7,8], 'C':'str', 'D':'str'}
dict((key, np.array(val) if key not in {'C', 'D'} else val for key, val in myDict.iteritems())
TerryA
  • 58,805
  • 11
  • 114
  • 143
  • Nice, but I get in ((key, val)) ----> 1 myDict = {key:np.array(val) if val not in {'C', 'D'} else val for key, val in myDict.iteritems()} TypeError: unhashable type: 'list' – labjunky Aug 28 '13 at 07:00
  • Try `ęlse key:val`. It seems Python thinks in `else val` you want to use `val` as a key (that's why it says `unhashable type`. – Andras Nemeth Aug 28 '13 at 07:04
  • @Cucu No, it was a simple typo of me checking if the list was in the set, when I should have been checking if the value (which can't be unhashable) was in the set – TerryA Aug 28 '13 at 07:05
1

To change all items except 'C' and 'D':

>>> myDict = {'A':[1,2,3,4], 'B':[5,6,7,8], 'C':'str', 'D':'str'}
>>> ignore = {'C', 'D'}
>>> new_dict = {k : v if k in ignore else np.array(v) for k,v in myDict.iteritems()}

the above dict-comprehension returns a new dictionary, to modify the original dict, try:

#myDict.viewkeys() - ignore --> set(['A', 'B'])
for key in myDict.viewkeys() - ignore:
    myDict[key] = np.array(myDict[key])

or if you only want to change 'A' and 'B':

for key in {'A', 'B'}:
    myDict[key] = np.array(myDict[key])
Ashwini Chaudhary
  • 244,495
  • 58
  • 464
  • 504
0

To

take a python dictionary of lists, convert the lists to numpy arrays, and restore them in the dictionary using list comprehension.

I would do:

myDict = {'A':[1,2,3,4], 'B':[5,6,7,8], 'C':'str', 'D':'str'}

def modifier(item):
    if type(item) == list:
        return np.array(item)
    else:
        return item

mod_myDict = {key: modifier(myDict[key]) for key in myDict.keys()}

The function then sets the restrictions you require in this case changing all lists into arrays. This returns:

{'A': array([1, 2, 3, 4]), 'B': array([5, 6, 7, 8]), 'C': 'str', 'D': 'str'}

Note: I believe this should be made shorter by using conditions in the if statement but I can't seem to figure it, something like

mod_myDict = {key: np.array(myDict[key]) if type(myDict[key])==list else key: myDict[key] for key in myDict.keys()}

That however, raises an error. Perhaps some more intelligent person than I knows why!

Greg
  • 11,654
  • 3
  • 44
  • 50
  • You may want something like the conditional comprehensions here: http://stackoverflow.com/questions/4260280/python-if-else-in-list-comprehension – Brighid McDonnell Feb 17 '15 at 23:59