【问题标题】:Python: Find the min, max value in a list of tuplesPython:在元组列表中查找最小值、最大值
【发布时间】: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次)。

标签: python list graphics


【解决方案1】:
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]

这也适用于列表中任意长度的元组。

【讨论】:

  • 你能多说一些关于 alist 前面的 * 的作用吗?没有 * 的 zip 行为真的完全不同......
  • @Andrew 当然,* 将列表拼接到函数的参数中。理解这一点的最好方法是通过示例: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
  • 谈到documentation 中的血腥细节,请务必查看 tiwo 的answer——这真的应该作为评论发布在这里——关于不需要zip 电话和只使用map(max, *alist)map(min, *alist)
【解决方案2】:
>>> 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)

【讨论】:

    【解决方案3】:

    zip 不是必需的,因此这简化为map(max, *data)(其中data 是相同长度的元组或列表的迭代器)。

    【讨论】:

    • 不确定您的意思,因为map(max, *alist)[7, 6]map(max, *iter(alist)) 也是如此)。
    • @martineau map(max, *alist) 返回[7, 5],就像map(max, zip(*alist)) 一样。
    • @flornquake:实际上它们都导致 Python 2.7 中的[7, 6]。我最初的评论是因为原始问题中没有关于使用zip 的内容,所以我不明白这个“答案”的相关性。也许这是对@cobbal 回答的评论。但它不适用于我的使用map(sorted, zip(*alist))
    • @martineau 实际上是[7, 5]。在问题的上下文中,这是最好的答案。
    • @Grief:使用 Python 2.7.12,我只运行了alist = [(1,6), (2,5), (2,4), (7,5)],然后运行map(max, *alist)(和map(max, *iter(alist))),结果是[7, 6]
    【解决方案4】:

    一般化的方法是这样的:

    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)
    • @Grief:套用一句流行的美国习语,概括性不是免费的。
    • @cobbal 由@tiwo 改进的答案并非不那么通用,而是更直接:list(map(max, *[(1,9),(2,8),(3,7)])) 返回[3, 9] 以及min-version 将返回[1, 7]
    【解决方案5】:

    使用枚举和列表理解的另一种解决方案

    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])
    

    【讨论】:

      【解决方案6】:

      对于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()

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-12-05
        • 2012-10-18
        • 2019-04-04
        • 2015-09-29
        • 1970-01-01
        • 2019-03-17
        • 1970-01-01
        • 2014-07-21
        相关资源
        最近更新 更多