【发布时间】:2010-10-23 06:22:17
【问题描述】:
alist = [(1,3),(2,5),(2,4),(7,5)]
我需要获取元组中每个位置的最小最大值。
狐狸示例: alist 的预期输出是
min_x = 1
max_x = 7
min_y = 3
max_y = 5
有什么简单的方法吗?
【问题讨论】:
-
你想迭代列表多少次? (4次、2次或1次)。
alist = [(1,3),(2,5),(2,4),(7,5)]
我需要获取元组中每个位置的最小最大值。
狐狸示例: alist 的预期输出是
min_x = 1
max_x = 7
min_y = 3
max_y = 5
有什么简单的方法吗?
【问题讨论】:
map(max, zip(*alist))
这首先解压缩您的列表,然后找到每个元组位置的最大值
>>> alist = [(1,3),(2,5),(2,4),(7,5)]
>>> zip(*alist)
[(1, 2, 2, 7), (3, 5, 4, 5)]
>>> map(max, zip(*alist))
[7, 5]
>>> map(min, zip(*alist))
[1, 3]
这也适用于列表中任意长度的元组。
【讨论】:
* 将列表拼接到函数的参数中。理解这一点的最好方法是通过示例:f(*[1, 2, 3]) 与 f(1, 2, 3) 完全相同,因此 zip(*[(1, 3), (2, 5), (2, 4), (7, 5)]) 与返回 zip((1, 3), (2, 5), (2, 4), (7, 5)) 的 zip((1, 3), (2, 5), (2, 4), (7, 5)) 相同。有关完整的血腥细节,请参阅documentation
zip 电话和只使用map(max, *alist) 和map(min, *alist)。
>>> from operator import itemgetter
>>> alist = [(1,3),(2,5),(2,4),(7,5)]
>>> min(alist)[0], max(alist)[0]
(1, 7)
>>> min(alist, key=itemgetter(1))[1], max(alist, key=itemgetter(1))[1]
(3, 5)
【讨论】:
zip 不是必需的,因此这简化为map(max, *data)(其中data 是相同长度的元组或列表的迭代器)。
【讨论】:
map(max, *alist) 是[7, 6](map(max, *iter(alist)) 也是如此)。
map(max, *alist) 返回[7, 5],就像map(max, zip(*alist)) 一样。
[7, 6]。我最初的评论是因为原始问题中没有关于使用zip 的内容,所以我不明白这个“答案”的相关性。也许这是对@cobbal 回答的评论。但它不适用于我的使用map(sorted, zip(*alist))。
[7, 5]。在问题的上下文中,这是最好的答案。
alist = [(1,6), (2,5), (2,4), (7,5)],然后运行map(max, *alist)(和map(max, *iter(alist))),结果是[7, 6]。
一般化的方法是这样的:
alist = [(1,6),(2,5),(2,4),(7,5)]
temp = map(sorted, zip(*alist))
min_x, max_x, min_y, max_y = temp[0][0], temp[0][-1], temp[1][0], temp[1][-1]
对于 Python 3,您需要将创建temp的行更改为:
temp = tuple(map(sorted, zip(*alist)))
这个想法可以抽象成一个在 Python 2 和 3 中都可以使用的函数:
from __future__ import print_function
try:
from functools import reduce # moved into functools in release 2.6
except ImportError:
pass
# readable version
def minmaxes(seq):
pairs = tuple()
for s in map(sorted, zip(*seq)):
pairs += (s[0], s[-1])
return pairs
# functional version
def minmaxes(seq):
return reduce(tuple.__add__, ((s[0], s[-1]) for s in map(sorted, zip(*seq))))
alist = [(1,6), (2,5), (2,4), (7,5)]
min_x, max_x, min_y, max_y = minmaxes(alist)
print(' '.join(['{},{}']*2).format(*minmaxes(alist))) # 1,7 4,6
triplets = [(1,6,6), (2,5,3), (2,4,9), (7,5,6)]
min_x, max_x, min_y, max_y, min_z, max_z = minmaxes(triplets)
print(' '.join(['{},{}']*3).format(*minmaxes(triplets))) # 1,7 4,6 3,9
【讨论】:
O(n×log(n)),而找到最小值是O(n)
list(map(max, *[(1,9),(2,8),(3,7)])) 返回[3, 9] 以及min-version 将返回[1, 7]
使用枚举和列表理解的另一种解决方案
alist = [(1,3),(2,5),(2,4),(7,5)]
for num, k in enumerate(['X', 'Y']):
print 'max_%s' %k, max([i[num] for i in alist])
print 'min_%s' %k, min([i[num] for i in alist])
【讨论】:
对于python 3:
alist = [(1,3),(2,5),(2,4),(7,5)]
[x_range, y_range] = list(zip(map(min, *test_list), map(max, *alist)))
print(x_range, y_range) #prints: (1, 7) (3, 5)
由于 zip/map 返回一个迭代器<object at 0x00>,你需要使用list()
【讨论】: