Python:将列表中的负值设为0

3 投票
3 回答
1440 浏览
提问于 2025-04-18 12:51

这看起来应该很简单,但我在把列表中的负数设置为0时遇到了问题。以下是我的代码:

def subtract_lists(list1, list2):
    list3 = list()
    for i in range(0,len(list1)):
            list3.append(list1[i]-list2[i])
    if i < 0:
            i = 0
    else:
            i = i
    return list3

我在使用matplotlib制作堆叠条形图时用到了这个函数。基本上,list2中的一些值比list1中的值要大。对于我手头的数据,出现负值是没有意义的。实际上,任何负值在图上都会显示为一根实心的条。

补充说明:我想说一下,图表的顶部是list3。

补充说明2:感谢大家的帮助。由于简单,我最终使用了这个:

def subtract_lists(list1, list2):
    list3 = list()
    for i in range(0,len(list1)):
            list3.append(max(list1[i]-list2[i], 0))
    return list3

不过我很感激所有的解决方案和帮助,我会尝试其他一些例子,作为学习的体验。

3 个回答

2

你把 i 设置成了零,而不是 list3[i] 里面的内容。

if list3[i] < 0:
    list3[i] = 0

你的 else 代码块里把 i=i 这样写,其实没什么用。你还缺少了一层缩进,正确的缩进应该是这样的:

def subtract_lists(list1, list2):
    list3 = list()
    for i in range(0,len(list1)):
        list3.append(list1[i]-list2[i])
        if list3[i] < 0:
            list3[i] = 0
return list3

不过,我觉得把这个函数写成这样会更清晰:

def subtract_lists(list1, list2):        
    list3 = []
    for a,b in zip(list1, list2):
        diff = a - b 
        list3.append(diff if diff > 0 else 0)
    return list3

当然,还有更简洁的解决方案(可以看看 DrV 的回答)。

3

一种方法是把列表转换成一个 numpyarray。这样进行减法运算就简单明了了,而且你还可以用 numpy.clip 把负值变成0。此外,numpy 的运算速度也快得多(如果你在意速度的话,不过在这种情况下似乎不太需要担心)。

import numpy as np

ar1 = np.array(list1)
ar2 = np.array(list2)

ar3 = np.clip(ar1 - ar2, 0, None)

如果你不想使用 numpy,那么只需把这一行

list3.append(list1[i] - list2[i])

改成这样

list3.append(max(list1[i] - list2[i], 0))

最后,当你在遍历列表以创建新列表时,使用列表推导式会更符合 Python 的风格:

list3 = [max(item1 - item2, 0) for item1, item2 in zip(list1, list2)]

当然,如果列表的大小适中,你还需要考虑 zip 实际上会复制列表这一点。所以如果使用 zip 时内存占用太大,你可以使用来自 itertools 模块的 izip。在这种情况下,它可以直接替代 zip

from itertools import izip
list3 = [max(item1 - item2, 0) for item1, item2 in izip(list1, list2)]
1
 list3 = []
 for i in range(len(list1)):
     list3.append(max(list1[i] - list2[i], 0))

或者

 list3 = [ max(li1-li2, 0) for li1, li2 in zip(list1, list2) ]

zip这个功能可以让你同时遍历两个列表,也就是说你可以同时拿到两个列表中相同位置的元素。个人认为这是用Python处理这个问题最优雅的方法,而且在处理两个列表时,这种方式可能也是最快的。max函数可以处理负数的情况,因为在这种情况下,零会比li1-li2大,然后被放入list3中。

jsw提供的解决方案也不错,但把列表转换成ndarray(NumPy数组)的过程比较慢。而且,遗憾的是,NumPy并不是Python标准库的一部分。

撰写回答