请问如何计算 Python 列表连续正数或连续负数的和? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
going
V2EX    Python

请问如何计算 Python 列表连续正数或连续负数的和?

  •  
  •   going 2021-08-19 12:06:05 +08:00 4182 次点击
    这是一个创建于 1589 天前的主题,其中的信息可能已经有所发展或是发生改变。

    请问如何高效计算 Python 列表连续正数或连续负数的和?

    案例:[1,3,5,-2,-1,3,5,2,-1,-3,-3]

    期望结果:[9,-3,10,-7]

    41 条回复    2021-08-26 14:52:06 +08:00
    unixeno
        1
    unixeno  
       2021-08-19 12:08:26 +08:00 via Android
    这个不是循环一遍就出来了吗
    zzzain46
        2
    zzzain46  
       2021-08-19 12:24:11 +08:00 via iPhone
    请学习 for 循环
    nobody1234
        3
    nobody1234  
       2021-08-19 12:26:44 +08:00 via iPhone
    维护好两个下标,遍历一次搞定
    lizytalk
        4
    lizytalk  
       2021-08-19 12:37:51 +08:0   6
    要说 pythonic 的话可以这样
    x = [1,3,5,-2,-1,3,5,2,-1,-3,-3]
    list(map(lambda item: sum(item[1]), groupby(x, key=lambda _: _ > 0)))
    lizytalk
        5
    lizytalk  
       2021-08-19 12:38:34 +08:00   1
    如果不需要 pythonic 的话还是 for 循环吧,遍历一遍就可以
    ch2
        6
    ch2  
       2021-08-19 12:40:25 +08:00
    nums=[1,3,5,-2,-1,3,5,2,-1,-3,-3]
    upper=[]
    lower=[]
    result=[]
    for num in nums:
    if num>0:
    if len(upper)==0:
    if len(lower)>0:
    result.append(sum(lower))
    lower=[]
    upper.append(num)
    else:
    if len(lower)==0:
    if len(upper)>0:
    result.append(sum(upper))
    upper=[]
    lower.append(num)
    if len(upper) > 0:
    result.append(sum(upper))
    if len(lower) > 0:
    result.append(sum(lower))
    print(result)
    kasusa
        7
    kasusa  
       2021-08-19 12:41:47 +08:00
    ```
    list1 = [1,3,5,-2,-1,3,5,2,-1,-3,-3] #原数据
    list2 = [] #结果输出
    a = list1[0] #计算从 2 开始

    for index in range(1,len(list1)):
    if list1[index] * list1[index - 1] < 0: #有换号,将结果添加到 list2,、把 a 归零
    list2.append(a)
    a = 0
    a += list1[index]
    else: #无换号,正常累加
    a += list1[index]
    list2.append(a) #将最后一个累加结果加入结果集

    print(list2)
    ```

    用到了数学中零点判定的知识。
    kasusa
        8
    kasusa  
       2021-08-19 12:42:35 +08:00
    ```
    V2EX 不支持这个 markdown 语法吗?

    ```
    kasusa
        9
    kasusa  
       2021-08-19 12:44:46 +08:00
    ```html
    是不是我的 markdown 语法有问题 >.>
    ```
    Kilerd
        10
    Kilerd  
       2021-08-19 12:45:25 +08:00
    作业请独立完成
    kasusa
        11
    kasusa  
       2021-08-19 12:47:10 +08:00
    xe2vherd
        12
    xe2vherd  
       2021-08-19 12:48:16 +08:00
    @lizytalk 你这个不是连续的吧
    msg7086
        13
    msg7086  
       2021-08-19 13:08:59 +08:00
    只懂 Ruby,写起来不难。
    x = [1, 3, 5, -2, -1, 3, 5, 2, -1, -3, -3]
    x.chunk(&:positive?).map(&:last).map(&:sum) #=> [9, -3, 10, -7]

    Python 里如果有类似的方法的话照着改一下就行了吧。
    huntagain2008
        14
    huntagain2008  
       2021-08-19 13:13:25 +08:00
    非程序员,看着文档学了 for 循环,不知道写的对不对。
    ``` python
    a=[1,3,5,-2,-1,3,5,2,-1,-3,-3]
    b=[]
    for i in range(len(a)):
    if i<len(a)-1:
    if a[i]*a[i+1]>0:
    a[i+1]=a[i]+a[i+1] # 比如 1+3 取 4 的结果放在下标 a[1]
    else:
    b+=[a[i]] # 遇到正负不同的,比如遇到-2 取 a[2]作为和
    kasusa
        15
    kasusa  
       2021-08-19 13:16:45 +08:00
    感觉小题目还挺益智的。
    不过 V2EX 显示代码真是难受。没有高亮、没有缩进。
    huntagain2008
        16
    huntagain2008  
       2021-08-19 13:17:06 +08:00
    @huntagain2008
    ``` python

    a=[1,3,5,-2,-1,3,5,2,-1,-3,-3]
    b=[]
    for i in range(len(a)):
    if i<len(a)-1:
    if a[i]*a[i+1]>0:
    a[i+1]=a[i]+a[i+1] # 比如 1+3 取 4 的结果放在下标 a[1]
    else:
    b+=[a[i]] # 遇到正负不同的,比如遇到-2 取 a[2]作为和

    ```
    huntagain2008
        17
    huntagain2008  
       2021-08-19 13:36:09 +08:00
    @huntagain2008 好吧,错了。
    a=[-2,1,3,5,-2,-1,3,5,2,-1,-3,-3]经过这段代码变成了[-2, 1, 4, 9, -2, -3, 3, 8, 10, -1, -4, -7]
    b 的值只有[-2, 9, -3, 10],后面的-12 没有求和了。
    learningman
        18
    learningman  
       2021-08-19 13:40:49 +08:00
    @kasusa #8 V2EX 只支持在主题中用 markdown,回复要贴代码要用 GitHub Gist
    huntagain2008
        19
    huntagain2008  
       2021-08-19 14:47:58 +08:00
    @huntagain2008 改了下,还是不知道这次对不对。
    >>>a=[-2, 1, 4, 9, -2, -3, 3, 8, 10, -1, -4, -7]
    >>> b=[]
    >>> for i in range(len(a)):
    ... if i<len(a)-1:
    ... if a[i]*a[i+1]>0:
    ... a[i+1]=a[i]+a[i+1] # 比如 1+3 取 4 的结果放在下标 a[1]
    ... else:
    ... b+=[a[i]] # 遇到正负不同的,比如遇到-2 取 a[2]作为和
    ... else:
    ... b+=[a[i]] # 最后一次求和
    ...
    >>> b
    [-2, 14, -5, 21, -12]
    huntagain2008
        20
    huntagain2008  
       2021-08-19 15:05:18 +08:00
    @huntagain2008 改了下,还是不知道这次对不对。
    >>>a=[-2, 1, 4, 9, -2, -3, 3, 8, 10, -1, -4, -7]
    >>> b=[]
    >>> for i in range(len(a)):
    ... if i<len(a)-1:
    ... ... if a[i]*a[i+1]>0:
    ... ... ... a[i+1]=a[i]+a[i+1] # 比如 1+3 取 4 的结果放在下标 a[1]
    ... ... else:
    ...... ... b+=[a[i]] # 遇到正负不同的,比如遇到-2 取 a[2]作为和
    ... else:
    ... ... b+=[a[i]] # 最后一次求和
    ...
    >>> b
    [-2, 14, -5, 21, -12]
    Gorgine
        21
    Gorgine  
       2021-08-19 15:55:55 +08:00
    from itertools import groupby
    your_list = [1, 3, 5, -2, -1, 3, 5, 2, -1, -3, -3]
    print([sum(item[1]) for item in groupby(your_list, lambda item: item > 0)])
    fkdtz
        23
    fkdtz  
       2021-08-19 16:14:56 +08:00   1
    话题无关:楼上代码没有一个能正常格式化的,贴图也是,鲜有一次就能贴对的。好奇为啥回帖的 markdown 要搞得这么难以捉摸。
        24
    lostvincent  
       2021-08-19 16:21:50 +08:00
    没写过 py,就写点伪代码了

    list = [...]
    result = []
    total = list[0]

    for (i = 1; i < len(list)); i++) {
    // total 和 list[i] 同符号
    if ((total > 0) === (list[i] > 0)) {
    total += list[i]
    } else {
    append(result, total)
    total = list[i]
    }
    }

    append(result, total)
    return result

    ========
    思路就是 total 记录累加
    total 和当前元素符号(正负号)不同了,就记录累加结果到 result,重置 total 然后开始下一轮
    题目写的是连续正负数,如果有 0 的话,遇到直接 continue
    lostvincent
    kasusa
        25
    kasusa  
       2021-08-19 16:29:51 +08:00
    @fkdtz 好像是只有帖子本身支持 markdown,但是回复贴不支持。
    zouzou0208
        26
    zouzou0208  
       2021-08-19 16:46:23 +08:00
    @lizytalk [sum(i[1]) for i in groupby(x, key=lambda _: _ > 0)]
    hahastudio
        27
    hahastudio  
       2021-08-19 18:36:01 +08:00
    可不可以有 0 ?有的话 0 怎么算?是继续还是单独算?
    gist.github.com/hahastudio/ec6c851a67c714ac40cf406a2aeeb525
    laduary
        28
    laduary  
       2021-08-19 22:10:45 +08:00
    用 arr[idx] * arr[idx -1] 判断正负
    https://paste.ubuntu.com/p/gpFNhcPwYm/
    mxT52CRuqR6o5
        29
    mxT52CRuqR6o5  
       2021-08-19 22:25:04 +08:00 via Android
    随便写写都是 o(n),都差不多的
    0ZXYDDu796nVCFxq
        30
    0ZXYDDu796nVCFxq  
       2021-08-19 22:37:00 +08:00 via Android
    @hahastudio 0 其实不影响结果
    zxCoder
        31
    zxCoder  
       2021-08-19 22:45:42 +08:00
    怎么个高效法。。。。
    yinheli
        32
    yinheli  
       2021-08-19 23:26:29 +08:00
    @lizytalk 直接把 group 结果做 sum 不就可以?

    ```python

    from itertools import groupby
    [sum(g) for _, g in groupby([1,3,5,-2,-1,3,5,2,-1,-3,-3], key=lambda x: x > 0)]

    ```
    ipwx
        33
    ipwx  
       2021-08-20 00:19:52 +08:00
    在 C++ 里面我就 i=0; j=0 开始原地求和,最后设一下 size,最高效。
    lixiang2017
        34
    lixiang2017  
       2021-08-20 01:08:23 +08:00 via Android
    说一下题外话。建议多刷题,这种在力扣属于 easy
    msg7086
        35
    msg7086  
       2021-08-20 05:39:21 +08:00
    @fkdtz 回帖啥时候有 markdown 的。
    2i2Re2PLMaDnghL
        36
    2i2Re2PLMaDnghL  
       2021-08-20 11:44:13 +08:00
    @lizytalk 这并不 pythonic,这是 functional
    不过 list(map(...)) 都可以轻易地改成 comprehension list
    yucongo
        37
    yucongo  
       2021-08-20 12:52:43 +08:00
    from functools import reduce

    lst = [1,3,5,-2,-1,3,5,2,-1,-3,-3]
    reduce(lambda x, y: x[:-1] + [x[-1] + lst[y]] if lst[y] * lst[y-1] > 0 else x +[lst[y]], range(1, len(lst[1:]) + 1), [lst[0]])
    # [9, -3, 10, -7]
    dallaslu
        38
    dallaslu  
       2021-08-20 19:01:20 +08:00
    @msg7086 肉眼 markdown
    rudy1224
        39
    rudy1224  
       2021-08-21 18:05:41 +08:00   1
    把目前回帖里面的方法对比了一下,加上了使用 NumPy+Numba 的数据:


    代码在此:
    <script src="https://gist.github.com/luhuidi/77ec31edfece0412d0058601e0f1a1ce.js"></script>
    imn1
        40
    imn1  
       2021-08-26 14:50:48 +08:00
    代码我就懒得写了,楼上很多 for 都能搞定,我给另一个解法:
    itertools.groupby,把连续+/-的分组,然后每组 sum 就是了,代码少很多,应该两三行就够了
    imn1
        41
    imn1  
       2021-08-26 14:52:06 +08:00
    呃,原来有人说了,漏看了,pass
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     960 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 19:22 PVG 03:22 LAX 11:22 JFK 14:22
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86