Taj Morton
Taj Morton

Reputation: 1638

Python map() dictionary values

I'm trying to use map() on the dict_values object returned by the values() function on a dictionary. However, I can't seem to be able to map() over a dict_values:

map(print, h.values())
Out[31]: <builtins.map at 0x1ce1290>

I'm sure there's an easy way to do this. What I'm actually trying to do is create a set() of all the Counter keys in a dictionary of Counters, doing something like this:

# counters is a dict with Counters as values
whole_set = set()
map(lambda x: whole_set.update(set(x)), counters.values())

Is there a better way to do this in Python?

Upvotes: 9

Views: 49962

Answers (2)

Quuxplusone
Quuxplusone

Reputation: 27200

You want the set-union of all the values of counters? I.e.,

counters[1].union(counters[2]).union(...).union(counters[n])

? That's just functools.reduce:

import functools

s = functools.reduce(set.union, counters.values())


If counters.values() aren't already sets (e.g., if they're lists), then you should turn them into sets first. You can do it using a dict comprehension using iteritems, which is a little clunky:

>>> counters = {1:[1,2,3], 2:[4], 3:[5,6]}
>>> counters = {k:set(v) for (k,v) in counters.iteritems()}
>>> print counters
{1: set([1, 2, 3]), 2: set([4]), 3: set([5, 6])}

or of course you can do it inline, since you don't care about counters.keys():

>>> counters = {1:[1,2,3], 2:[4], 3:[5,6]}
>>> functools.reduce(set.union, [set(v) for v in counters.values()])
set([1, 2, 3, 4, 5, 6])

Upvotes: 0

senderle
senderle

Reputation: 151007

In Python 3, map returns an iterator, not a list. You still have to iterate over it, either by calling list on it explicitly, or by putting it in a for loop. But you shouldn't use map this way anyway. map is really for collecting return values into an iterable or sequence. Since neither print nor set.update returns a value, using map in this case isn't idiomatic.

Your goal is to put all the keys in all the counters in counters into a single set. One way to do that is to use a nested generator expression:

s = set(key for counter in counters.values() for key in counter)

There's also the lovely dict comprehension syntax, which is available in Python 2.7 and higher (thanks Lattyware!) and can generate sets as well as dictionaries:

s = {key for counter in counters.values() for key in counter}

These are both roughly equivalent to the following:

s = set()
for counter in counters.values():
    for key in counter:
        s.add(key)

Upvotes: 19

Related Questions