invert dictionary with list &c
anton muhin
antonmuhin.REMOVE.ME.FOR.REAL.MAIL at rambler.ru
Wed Nov 26 13:05:12 EST 2003
Des Small wrote:
> Lately I have found myself using a pattern to make new dictionaries
> quite often, by which I mean twice:
>
> def invert(d):
> nd = {}
> [nd.setdefault(val, []).append(key) for k, v in d]
> return nd
>
> def count(l):
> d = {}
> [d.setdefault(w, 0) += 1 for w in l]
> return d
>
> Is this the pythonic way to do such things? Ideally I'd like to write
> them as one liners, but I can't see how.
>
> Des
Most pythonic way IMHO would be:
def invert(d):
nd = {}
for k, v in d.iteritems():
nd[v] = nd.get(k, []) + [k]
return nd
def count(l):
d = {}
for e in l:
d[e] = d.get(e, 0) + 1
return d
Or to define dict with default values:
import copy
class defdict(dict):
def __init__(self, default = None):
self._default = default
super(dict, self).__init__(self)
def __getitem__(self, k):
return self.get(k, copy.deepcopy(self._default)) # or setdefault
when
def invert(d):
nd = defdict([])
for k, v in d.iteritems():
nd[v] += [k]
return nd
def count(l):
d = defdict(0)
for e in l:
d[e] += 1
return d
However, if you insist on one-liners, I can suggest some ;):
def count(l):
return reduce(
lambda d, e: (d.update(dict([(e, d.get(e, 0) + 1)])), d)[1],
l, {}
)
def invert(d):
return reduce(
lambda d, (k, v): (d.update(dict([(v, d.get(v, []) + [k])])), d)[1],
d.iteritems(), {}
)
(given in several lines, but can be written in one)
or even
count = lambda l: reduce(
lambda d, e: (d.update(dict([(e, d.get(e, 0) + 1)])), d)[1],
l, {}
)
:)
regards,
anton.
More information about the Python-list
mailing list