Clev3r
Clev3r

Reputation: 1588

Mapping func over dictionary

How might one map a function over certain values in a dictionary and also update those values in the dictionary?

dic1 = { 1 : [1, 2, 3, 4], 2 : [2, 3, 5, 5], 3 : [6, 3, 7, 2] ... }
map(func, (data[col] for data in dic1.itervalues()))

This is sort of what I'm looking for, but I need a way to reinsert the new func(val) back into each respective slot in the dict. The function works fine, and printed it returns all the proper index values with the func applied, but I can't think of a good way to update the dictionary. Any ideas?

Upvotes: 1

Views: 175

Answers (2)

abarnert
abarnert

Reputation: 366133

You don't want to use map for updating any kind of sequence; that's not what it's for. map is for generating a new sequence:

dict2 = dict(map(func, dict1.iteritems()))

Of course func has to take a (key, old_value) and return (key, new_value) for this to work as-is. If it just returns, say, new_value, you need to wrap it up in some way. But at that point, you're probably better off with a dictionary comprehension than a map call and a dict constructor:

dict2 = {key: func(value) for key, value in dict1.itervalues()}

If you want to use map, and you want to mutate, you could do it by creating a function that updates things, like this:

def func_wrapped(d, key):
    d[key] = func(d[key])
map(partial(func_wrapped, d), dict1)

(This could even be done as a one-liner by using partial with d.__setitem__ if you really wanted.)

But that's a silly thing to do. For one thing, it means you're building a list of values just to throw them away. (Or, in Python 3, you're not actually doing anything unless you write some code that iterates over the map iterator.) But more importantly, you're making things harder for yourself for no good reason. If you don't need to modify things in-place, don't do it. If you do need to modify things in place, use a for loop.

PS, I'm not saying this was a silly question to ask. There are other languages that do have map-like mutating functions, so it wouldn't be a silly thing to do in, say, C++. It's just not pythonic, and you wouldn't know that without asking.

Upvotes: 3

mgilson
mgilson

Reputation: 310257

Your function can mutate the list:

>>> d = {1:[1],2:[2],3:[3]}
>>> def func(lst):
...     lst.append(lst[0])
...     return lst
... 
>>> x = map(func,d.values())
>>> x
[[1, 1], [2, 2], [3, 3]]
>>> d
{1: [1, 1], 2: [2, 2], 3: [3, 3]}

however, please note that this really isn't idiomatic python and should be considered for instructional/educational purposes only ... Usually if a function mutates it's arguments, it's polite to have it return None.

Upvotes: 1

Related Questions