在 (x, y) 对列表的字典中,即使这些值位于不同的 (x, y) 对中,Python 3 中查找字典中最大 x 和最大 y 的最有效方法是什么?
roi = { '26580.BOT': [(107, 1006),
(107, 973)],
'26580.TOP': [(107, 1008),
(107, 1040),
(107, 1072),
(107, 1648)],
'26582.TOP': [(113, 977)],
'26685.TOP': [(105, 974)]}
请您参考如下方法:
我个人会在 values 上使用 for 循环,因为它会对数据进行单次传递并且节省空间,但如果您更喜欢难以阅读的单行代码,总有 reduce :)
>>> import functools, itertools
>>> def max_tuple(t1, t2): return max(t1[0],t2[0]), max(t1[1],t2[1])
...
>>> ts = itertools.chain.from_iterable(roi.values())
>>> functools.reduce(max_tuple, ts)
(113, 1648)
请注意,这是节省空间的!如果您担心速度,请使用循环,或者,您可以尝试使用此替代实现来减少函数:
>>> def max_tuple2(t1, t2):
... (a,b), (x,y) = t1, t2
... return (a if a > x else x, b if b > y else y)
...
这对我来说测试速度要快得多,让我们做一个更大的测试字典:
>>> roi2 = {k+str(i): v*100 for k, v in roi.items() for i in range(100)}
现在,一些测试:
>>> timeit.timeit('ts = itertools.chain.from_iterable(roi2.values()); functools.reduce(max_tuple, ts)', 'from __main__ import functools, itertools, max_tuple, roi2;', number=100)
4.612322789034806
>>> timeit.timeit('ts = itertools.chain.from_iterable(roi2.values()); functools.reduce(max_tuple2, ts)', 'from __main__ import functools, itertools, max_tuple2, roi2;', number=100)
1.7526514289784245
使用 max_tuple2 的速度是原来的两倍多。但是,如果您关心速度,请使用 naive-forloop 方法。这是@AdiC 的解决方案,经过了一些美化:
>>> def max_from_values(d):
... m1 = m2 = float('-inf')
... for tlist in d.values():
... for a, b in tlist:
... if a > m1:
... m1 = a
... if b > m2:
... m2 = b
... return m1, m2
...
>>> max_from_values(roi2)
(113, 1648)
看,它比之前最快的速度快了三倍多,几乎比原来快十倍:
>>> timeit.timeit('max_from_values(roi2)', 'from __main__ import max_from_values, roi2;', number=100)
0.4867470810422674
