Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 此函数同时检索最小值和最大值是否比单独使用最小值和最大值快?_Python_Max_Min - Fatal编程技术网

Python 此函数同时检索最小值和最大值是否比单独使用最小值和最大值快?

Python 此函数同时检索最小值和最大值是否比单独使用最小值和最大值快?,python,max,min,Python,Max,Min,我有一个函数可以同时检索列表的最小值和最大值: def min_max(iterable, key=None): """Retrieve the min and max values of `iterable` simultaneously.""" if key is None: key = lambda x: x if not iterable: return None, None min_ = max_ = key(iterable[0])

我有一个函数可以同时检索列表的最小值和最大值:

def min_max(iterable, key=None):
    """Retrieve the min and max values of `iterable` simultaneously."""
    if key is None: key = lambda x: x
    if not iterable:
        return None, None
    min_ = max_ = key(iterable[0])
    for i in iterable[1:]:
        if key(i) > key(max_): max_ = i
        if key(i) < key(min_): min_ = i
    return min_, max_
def min_max(iterable,key=None):
“”“同时检索'iterable'的最小值和最大值。”“”
如果key为None:key=lambda x:x
如果不适用:
返回None,None
最小值=最大值=键(iterable[0])
因为我在iterable[1:]:
如果键(i)>键(max):max=i
如果键(i)<键(最小值):最小值=i
返回最小值,最大值_

但这让我想知道,既然我在for循环中进行了两次比较,单独使用
min
max
会不会更快?如果是,我如何编辑此函数以提高效率?

在列表中查找最小值或最大值的代价不是比较。比较值非常快,在这里不会产生问题。相反,影响运行时的是循环

当您使用
min()
max()
时,它们中的每一个都必须在iterable上迭代一次。它们是分开做的,所以当您需要最小值和最大值时,通过使用内置函数,您需要迭代两次

您的函数只需在其上迭代一次,因此其理论运行时间较短。现在,正如chepter在评论中提到的,
min
max
都是实现的,因此它们肯定比您自己在Python代码中实现时要快

现在,这在很大程度上取决于您的iterable,这两个本机循环是否比Python函数快。对于较长的列表,迭代它已经很昂贵,迭代一次肯定会更好,但对于较短的列表,您可能会使用本机代码获得更好的结果。我不知道确切的阈值在哪里,但是你可以很容易地测试出你的实际数据什么更快。不过,在大多数情况下,它很少起作用,因为最小/最大值不会成为应用程序的瓶颈,所以在它成为问题之前,您不应该担心它


顺便说一句,您的实现现在有一些问题,如果您想使用它,您应该解决这些问题:

  • 它要求
    iterable
    是一个序列,而不是一个iterable(因为您对它使用索引)
  • 您还要求它至少有一个技术上不需要的项目。虽然您确实检查了
    不可编辑
    ,但这并不一定会告诉您有关序列/可编辑长度的信息。自定义类型可以轻松提供自己的布尔值和/或序列行为
  • 最后,使用iterable项的键控值初始化
    \u min
    \u max
    ,但稍后(正确地)只从iterable中分配原始项
因此,我建议您改用迭代器,并解决关键问题您还可以存储关键结果以节省更复杂的关键函数的计算:

it = iter(iterable)
try:
    min_ = max_ = next(it)
    minv = maxv = key(min_)
except StopIteration:
    return None, None

for i in it:
    k = key(i)
    if k > maxv:
        max_, maxv = i, k
    elif k < minv:
        min_, minv = i, k
使用此代码:

for i in iterable[1:]:
    if key(i) > key(max_): 
        max_ = i
    elif key(i) < key(min_):
        min_ = i
iterable[1:]中的i的

如果键(i)>键(最大值):
最大值=i
elif键(i)<键(最小值):
最小值=i
请检查此处:

这并不完全是您所看到的,但我可以减少循环:

def min_max(iterable):
    if not iterable:
        raise Exception('Required iterable object')
    _min = _max = iterable[0]
    ind = 0
    if len(iterable) & 1:
        ind = 1
    for elm in iterable[1::2]:
        ind += 2
        try:
            if iterable[ind] < iterable[ind + 1]:
                if _min > iterable[ind]:
                    _min = iterable[ind]
                if _max < iterable[ind + 1]:
                    _max = iterable[ind + 1]
            else:
                if _min > iterable[ind + 1]:
                    _min = iterable[ind + 1]
                if _max < iterable[ind]:
                    _max = iterable[ind]
        except:
            pass
    return _min, _max

print min_max([11,2,3,5,0,1000,14,5,100,1,999])

假设
iterable
中至少有一个键。否则,这将在调用
min\ux=max\ux…
时消失。为什么要使用一个只返回其参数的函数来访问这些值?折衷是在Python级别对列表进行一次遍历,而在C级别进行两次遍历。哪种方法更快可能取决于列表的长度,但我怀疑,除了非常大的列表之外,后者将更快。对其进行分析并查看。难道您不能对min-an
elif
进行第二次检查吗?一次通过算法在处理任意iterable时可能具有相当大的优势,但使用
iterable[0]
iterable[1://code>则否定了这一点;没有回答这个问题。也不知道你在那里做什么…好吧,我提供了一个更好的解决方案,如果业主不喜欢,我会删除它。我正在将循环数减少到n/2,@user3398620如果您不喜欢,请告诉我:)我将删除它。好吧,我可以随时进行循环展开以删除迭代;但这不会改变复杂性(我认为这会使函数更加复杂)。此外,您的解决方案不支持键函数,并且还基于不可编辑的序列(甚至比OP更为如此)。我不是向下投票人,但我想指出,对于较长的列表,仅迭代一次应该比迭代两次更快的想法是误导的。考虑的两种算法都是
O(N)
,因此无论输入的大小,它们的相对速度应该保持不变。只有当输入相当大时(为了克服任何可能不同的恒定开销),这才可能是正确的,但是从10000项到1000000项的相对性能不会有太大的差异。@Blckknght当然,它们在O表示法中被认为是相等的,但它们仍然有不同的执行时间,这在优化代码时往往很重要。如果您在应用程序中反复计算最小值和最大值,那么您可能希望对此进行一些微优化,并选择一个更快的值,即使两者都是
O(n)
。如果你读了我的答案,你会发现,虽然我指出了不同之处,但实际上我还是建议使用单独的函数,因为微优化通常是不必要的。
def min_max(iterable):
    if not iterable:
        raise Exception('Required iterable object')
    _min = _max = iterable[0]
    ind = 0
    if len(iterable) & 1:
        ind = 1
    for elm in iterable[1::2]:
        ind += 2
        try:
            if iterable[ind] < iterable[ind + 1]:
                if _min > iterable[ind]:
                    _min = iterable[ind]
                if _max < iterable[ind + 1]:
                    _max = iterable[ind + 1]
            else:
                if _min > iterable[ind + 1]:
                    _min = iterable[ind + 1]
                if _max < iterable[ind]:
                    _max = iterable[ind]
        except:
            pass
    return _min, _max

print min_max([11,2,3,5,0,1000,14,5,100,1,999])
(0, 1000)