Here's my (tongue in cheek) answer:
myDict = reduce(lambda d, t: (d.__setitem__(t[1], d.get(t[1], 0) + t[2]), d)[1], myTupleList, {})
It is ugly and bad, but here is how it works.
The first argument to reduce (because it isn't clear there) is lambda d, t: (d.__setitem__(t[1], d.get(t[1], 0) + t[2]), d)[1]
. I will talk about this later, but for now, I'll just call it joe
(no offense to any people named Joe intended). The reduce function basically works like this:
joe(joe(joe({}, myTupleList[0]), myTupleList[1]), myTupleList[2])
And that's for a three element list. As you can see, it basically uses its first argument to sort of accumulate each result into the final answer. In this case, the final answer is the dictionary you wanted.
Now for joe
itself. Here is joe
as a def
:
def joe(myDict, tupleItem):
myDict[tupleItem[1]] = myDict.get(tupleItem[1], 0) + tupleItem[2]
return myDict
Unfortunately, no form of =
or return
is allowed in a Python lambda
so that has to be gotten around. I get around the lack of =
by calling the dict
s __setitem__
function directly. I get around the lack of return in by creating a tuple with the return value of __setitem__
and the dictionary and then return the tuple element containing the dictionary. I will slowly alter joe
so you can see how I accomplished this.
First, remove the =
:
def joe(myDict, tupleItem):
# Using __setitem__ to avoid using '='
myDict.__setitem__(tupleItem[1], myDict.get(tupleItem[1], 0) + tupleItem[2])
return myDict
Next, make the entire expression evaluate to the value we want to return:
def joe(myDict, tupleItem):
return (myDict.__setitem__(tupleItem[1], myDict.get(tupleItem[1], 0) + tupleItem[2]),
myDict)[1]
I have run across this use-case for reduce
and dict
many times in my Python programming. In my opinion, dict
could use a member function reduceto(keyfunc, reduce_func, iterable, default_val=None)
. keyfunc
would take the current value from the iterable and return the key. reduce_func
would take the existing value in the dictionary and the value from the iterable and return the new value for the dictionary. default_val
would be what was passed into reduce_func
if the dictionary was missing a key. The return value should be the dictionary itself so you could do things like:
myDict = dict().reduceto(lambda t: t[1], lambda o, t: o + t, myTupleList, 0)