最大(*args,关键= ...)。如何修改键以获取某些值?

max(*args, key = ... ). How to modify key to get just certain values?

我对 max(*args, key = ..) 函数有点困惑。假设我有以下列表:my_list = [2, 3, 4, -5, -2, -1]。我想在 my_list 的负值范围内找到最大值。为此,我使用以下代码 max(my_list, key = lambda x: x<0),但它给了我 -5。你能给我解释一下逻辑吗?

你在调用 max(my_list, key = lambda x: x<0) 时所做的是说:“列表中的哪个值最大,但是比较每个元素的表达式 (x<0) 的结果值而不是元素的价值。” 因此,max 运算符在决定哪个最大时基本上将列表视为 [False, False, False, True, True, True],而在 python 中,这等同于 [0, 0, 0, 1, 1, 1]max returns它看到的第一个最大元素,对应于-5。

您可能希望先将列表过滤为仅负值,然后对结果调用 max

我会使用列表理解来过滤掉正值,然后找到最大值。

max([i for i in my_list if i < 0]) 

虽然我不会为此单独使用 max,但您 可以 ,使用不会折叠多个值的适当 key 函数:

max(my_list, key=lambda x: -float('inf') if x > 0 else x)

这会导致所有正值进行比较,就好像它们是负无穷大一样,负无穷大不能是包含任何 non-positive 个值的列表中的最大值。

(如果所有值 都是 都是正数,您需要以某种方式调整它,因为它仍然 return 列表中的第一个值: 没有连续的值更大。除非要求,否则我认为这超出了当前陈述的问题范围。)

是的,您可以使用 max 函数在一行中完成此操作。我在下面解释。

还有一个比我最后解释的列表理解更好的方法。

您的问题原因:

如果您提供了 key 参数,这就是 max 函数的工作方式。它将遍历列表的值,然后对每个值应用 lambda 函数(名为 key)。所以所有的值都将映射到 lambda 函数的结果。然后它对这些结果执行 max 函数。

所以当你有 key=lambda x: x<0 这将 return TrueFalse 因为 x<0 是一个布尔表达式。所以结果列表就像 [False, False, False, True, True, True]。这些 FalseTrue 值被处理为 max 函数的 01 值。

max 函数获取 [0, 0, 0, 1, 1, 1] 并找到列表中第一个最大数字(数字 1),即对应列表中的第一个 1到原始列表中的编号-5。

解决方案:

有多种方法可以找到最大负数,例如使用 for 循环或列表理解,甚至组合 filtermax。但是,为了更好地理解 max 函数及其参数,我向您展示了如何通过 max 函数执行您想要的操作(找到最大负数)。

max(my_list, key = lambda x: min(my_list) if x>=0 else x)

此代码将找到最大负数。

此代码如何工作?

提供的 lambda 表达式会将所有数字映射为:

如果数字是 正数 我们将 max 函数的值替换为最小数,这样它就永远不会被选为最大负数。 (我们可以通过 filter 删除所有负数来完成此操作,但我决定只使用 lambda 来完成所有工作以向您展示方法。)

如果数字是负数,它将保持它自己的价值。因此,对于您的示例,列表是 my_list = [2, 3, 4, -5, -2, -1] 它将创建 [-5, -5, -5, -5, -2, -1] 然后它将在此列表上执行 max 函数,它将找到 -1 数字你要。

希望它能帮助您了解如何仅通过 max 函数求最大负数以及最大函数的工作方式。

注意:此代码不是最优的。因为每次它计算最小值。此代码仅供学习使用。

最好的方法

我认为更好的代码是这样的:

max((num for num in my_list if num<0))

请注意,这不是列表理解。它 优于列表理解 。相反,它创建了一个 generator,一次只处理一个值。这比列表理解更好,因为列表理解会立即创建整个列表,然后将其发送给 max 函数。但是这段代码一次处理每个值并且不会用大列表填充内存。所以这样效率更高。