Request for useful functions on dicts

L

Leif

Hi, everybody. I am trying to collect all the functions I've found useful for working with dicts into a library:

https://github.com/leifp/dictutil

If you have a favorite dict-related func / class, or know of similar projects, please let me know (or open an issue on github). Bear in mind that the functions don't even have to come from python; if you have a favorite PHP /APL / COBOL / etc associative array function, that's fair game.

Thanks,
Leif

P. S. I'm participating in Julython [ http://www.julython.org/ ], and it'sfun. You should all join and show everyone that your city has the most open source python activity.
 
I

Ian Kelly

Hi, everybody. I am trying to collect all the functions I've found usefulfor working with dicts into a library:

https://github.com/leifp/dictutil

If you have a favorite dict-related func / class, or know of similar projects, please let me know (or open an issue on github). Bear in mind that the functions don't even have to come from python; if you have a favorite PHP/ APL / COBOL / etc associative array function, that's fair game.

Nothing in particular comes to mind, but I'll be happy to critique
what you've already got.

One thing that bothers me a bit is that get_in will accept any
iterable, but set_in and update_in can only accept a sequence in order
to do the slicing. Here's an alternate implementation for set_in that
takes any iterable:

def set_in(d, ks, v):
tmp = d
i = None
for i, next_key in enumerate(ks):
if i > 0:
tmp = tmp.setdefault(current_key, {})
current_key = next_key
if i is None:
raise KeyError("Empty keys iterable")
tmp[current_key] = v

update_in could be rewritten similarly. You might also notice that
I'm not returning d here. That's because the Pythonic way is to
either create a new object and return it, or mutate the existing
object and return None. If you mutate the existing object and return
it, that can lead to confusion about which style the method takes.
This is why list.append (for example) always returns None.

In Python 2.7+, intersection and difference could be written using
dictviews, which act like sets.

partition_on_value, partition_on_key: The only difference between
these is whether it passes the key or the value to the predicate. You
could just pass both and let the predicate decide which one (or both)
to use, and then you only need a single function. Also, why a
predicate specifically? This could be generalized to partition any
equivalence relation, not just those with only two equivalence
classes:

def partition(f, d):
"""Partition the dict according to an equivalence relation.

Calls f(key, value) for all (key, value) pairs in the dict d. The return
value of f must be hashable.
Returns a new dict where the keys are distinct return values of f, and the
values are dicts containing the equivalence classes distinguished by those
return values.
"""
partition = defaultdict(dict)
for k, v in d.iteritems():
partition[f(k, v)][k] = v
return partition

If you still wanted the predicate semantics, you could then define
that as a wrapper:

def partition_pred(f, d):
p = partition(lambda k,v: bool(f(k,v)), d)
return p[True], p[False]

issubdict could be implemented as a subset operation. I haven't timed
it so it may not really be any faster, but this way the looping is in
C instead of in Python:

def issubdict(d1, d2):
return set(d1.items()).issubset(d2.items())

Finally, isempty(d) is basically equivalent to "not d", which is both
shorter and faster.

Cheers,
Ian
 
L

Leif

Thanks for the suggestions, Ian! I implemented most of them and pushed thecode.
That's because the Pythonic way is to either create a new object and
return it, or mutate the existing object and return None.

You're saying what I was already thinking.
In Python 2.7+, intersection and difference could be written using
dictviews, which act like sets.

I'm debating with myself right now whether to support 2.5 and 2.6.
def partition(f, d):

Good idea, thanks.
issubdict could be implemented as a subset operation. I haven't timed

The current implementation is a bit faster, and it's quite a bit faster on the common (for me) case, where one argument is much smaller than the other.. I wrote it that way because if m=len(first), n=len(second), the amount of work is O(min(m,n)). Your implementation is O(m + n). Not really a big deal, unless e.g. m << n.

--Leif
 
L

Leif

Thanks for the suggestions, Ian! I implemented most of them and pushed thecode.
That's because the Pythonic way is to either create a new object and
return it, or mutate the existing object and return None.

You're saying what I was already thinking.
In Python 2.7+, intersection and difference could be written using
dictviews, which act like sets.

I'm debating with myself right now whether to support 2.5 and 2.6.
def partition(f, d):

Good idea, thanks.
issubdict could be implemented as a subset operation. I haven't timed

The current implementation is a bit faster, and it's quite a bit faster on the common (for me) case, where one argument is much smaller than the other.. I wrote it that way because if m=len(first), n=len(second), the amount of work is O(min(m,n)). Your implementation is O(m + n). Not really a big deal, unless e.g. m << n.

--Leif
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,962
Messages
2,570,134
Members
46,690
Latest member
MacGyver

Latest Threads

Top