filter()ing a dict

John Roth newsgroups at jhrothjr.com
Thu Aug 7 16:39:44 CEST 2003


According to the doc, filter() processes sequences,
iterators and objects that support the iterator protocol.
A dict is none of those things, unless it supports the iterator
protocol, which is not mentioned in the documentation
as of 2.2.3. Possibly it does in 2.3.0.

If you want to use filter() to process a dict, use the .items()
method. That will get you a list of tuples, where each tuple
contains the key and value. .iteritems() will also work,
of course.

What is returned will be a list of tuples, which you can
use to build a dict.

I'm surprised that what you tried worked at all. The
2.2.3 documentation on dictionaries doesn't suggest that
a dictionary supports the iteration protocol, or what it
returns in that context.

John Roth

"Robin Cull" <robin.cull at pace.co.uk> wrote in message
news:16469f07.0308070559.aed41a at posting.google.com...
> Imagine I have a dict looking something like this:
>
> myDict = {"key 1": ["value 1", "value 2", "value 3", "value 4"], "key
> 2": ["value 1", "value 2"], "key 3": ["value2", "value 3", "value 4"],
> "key 4": ["value 1", "value 2", "value 3", "value 4"]}
>
> That is, a set of keys which have a variable length list of associated
> values after them.  What I want to do is filter out a subset of this
> dict to produce another dict that satisfies a set of criteria (in this
> case whether it contains all four values) to end up with something
> like this:
>
> {"key 1": ["value 1", "value 2", "value 3", "value 4"], "key 4":
> ["value 1", "value 2", "value 3", "value 4"]}
>
> I've tried using the filter() function so I wrote a small function
> that returned True or False depending on whether the length of the
> list was what I wanted e.g.
>
> def f(item):
>     if len(item) == 4:
>         return True
>     else:
>         return False
>
> I then called filter(f, myDict).
>
> I was expecting to be returned a dict which was the subset of myDict
> that satisfied f.
>
> This did not happen; the item passed to f was each key of the dict,
> not each value list.  The call to filter returned an empty list (as
> obviously none of the keys satisfied the criteria).  If anything I
> would have expected an empty dict back as according to the docs:
>
>     ""filter(function, sequence)" returns a sequence (of the same
> type, if possible) consisting of those items from the sequence for
> which function(item) is true."
>
> The important bit here is "of the same type, if possible" which I
> understood to mean if passed a dict it would return a dict.
>
> I've tried calling filter(f, myDict.values()) which works and I get a
> list like this returned:
>
> [["value 1", "value 2", "value 3", "value 4"], ["value 1", "value 2",
> "value 3", "value 4"]]
>
> Sort of what I want but I've lost the associativity with the key which
> was kind of the point in using a dict in the first place.
>
> I'm guessing that filter() does not work on a dict in the way I think
> it should.
>
> I can write something to get around the behaviour in this particular
> case (although suggestions would be welcome).
>
> My question is, does anybody else think that when calling filter(f,
> dict), it should return a dict of the keys and values of the former
> dict where the values satisfy the conditions defined by f()?
>
> Are there reasons for it not to work this way?  I must admit I've not
> looked into this carefully, just in the context of my script it'd be
> useful to.
>
> What are the side effects of making filter() work this way?
>
> Thanks all.
>
> Regards,
>
> Robin






More information about the Python-list mailing list