map-like function on dict values?
Huaiyu Zhu
huaiyu at gauss.almadan.ibm.com
Thu Feb 28 13:46:48 EST 2002
On Wed, 27 Feb 2002 19:57:21 -0600, Skip Montanaro <skip at pobox.com> wrote:
>
> Huaiyu> Is there a way to do this
> Huaiyu> for k, v in dict.items():
> Huaiyu> dict[k] = f(v)
>
> Huaiyu> without involving a Python for loop?
>
>Check out the operator module. In particular, operator.setitem will
>probably do what you want:
>
> import operator
> keys = dict.keys()
> vals = map(f, dict.values())
> map(operator.setitem, [dict]*len(keys), keys, vals)
This works. Thank you. It speeds up by more than a factor of four againt
for loop iteration. The disadvantage is that it builds at least five
temporary lists, so it is not usable if memory is constrained.
>
> Huaiyu> I'd imagine that a function implemented in C could speed things
> Huaiyu> up quite a bit.
>
>It all depends on how expensive f() is related to the overhead of a for loop
>and the cost of getting map ramped up. Don't rely on your instincts.
>Benchmark it.
Well, I can't benchmark it until it is available. :-(
What I was alluding to is that a built-in iteration would loop over all the
values held in the dict without touching the keys at all, and certainly
without building temporary lists. I imagine this would also bypass all the
the hash calculation and conflict resolution. The fact that your solution
speeds up so much despite building temporary lists shows that a C loop over
values could save even more.
Huaiyu
PS. The test and result:
import operator
from time import time
def iteritems(f, d):
for k, v in d.items():
d[k] = f(v)
def mapvalue(f, d):
keys = d.keys()
map(operator.setitem, [d]*len(keys), keys, map(f, d.values()))
def timeit(test, f, d):
_time = time()
test(f, d)
print time() - _time
if __name__ == '__main__':
d = {}
for i in range(1000000):
d[i] = None
def f(x): pass
timeit(iteritems, f, d)
timeit(mapvalue, f, d)
# result
19.8180559874
4.17512202263
More information about the Python-list
mailing list