请问如何计算 Python 列表连续正数或连续负数的和? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
推荐学习书目
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

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

  •  
  •   going Aug 19, 2021 4350 views
    This topic created in 1715 days ago, the information mentioned may be changed or developed.

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

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

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

    41 replies    2021-08-26 14:52:06 +08:00
    unixeno
        1
    unixeno  
       Aug 19, 2021 via Android
    这个不是循环一遍就出来了吗
    zzzain46
        2
    zzzain46  
       Aug 19, 2021 via iPhone
    请学习 for 循环
    nobody1234
        3
    nobody1234  
       Aug 19, 2021 via iPhone
    维护好两个下标,遍历一次搞定
    lizytalk
        4
    lizytalk  
       Aug 19, 2021   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  
       Aug 19, 2021   1
    如果不需要 pythonic 的话还是 for 循环吧,遍历一遍就可以
    ch2
        6
    ch2  
       Aug 19, 2021
    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  
       Aug 19, 2021
    ```
    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  
       Aug 19, 2021
    ```
    V2EX 不支持这个 markdown 语法吗?

    ```
    kasusa
        9
    kasusa  
       Aug 19, 2021
    ```html
    是不是我的 markdown 语法有问题 >.>
    ```
    Kilerd
        10
    Kilerd  
       Aug 19, 2021
    作业请独立完成
    kasusa
        11
    kasusa  
       Aug 19, 2021
    xe2vherd
        12
    xe2vherd  
       Aug 19, 2021
    @lizytalk 你这个不是连续的吧
    msg7086
        13
    msg7086  
       Aug 19, 2021
    只懂 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  
       Aug 19, 2021
    非程序员,看着文档学了 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  
       Aug 19, 2021
    感觉小题目还挺益智的。
    不过 V2EX 显示代码真是难受。没有高亮、没有缩进。
    huntagain2008
        16
    huntagain2008  
       Aug 19, 2021
    @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  
       Aug 19, 2021
    @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  
       Aug 19, 2021
    @kasusa #8 V2EX 只支持在主题中用 markdown,回复要贴代码要用 GitHub Gist
    huntagain2008
        19
    huntagain2008  
       Aug 19, 2021
    @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  
       Aug 19, 2021
    @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  
       Aug 19, 2021
    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  
       Aug 19, 2021   1
    话题无关:楼上代码没有一个能正常格式化的,贴图也是,鲜有一次就能贴对的。好奇为啥回帖的 markdown 要搞得这么难以捉摸。
    lostvincent
        24
    lostvincent  
       Aug 19, 2021
    没写过 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
    kasusa
        25
    kasusa  
       Aug 19, 2021
    @fkdtz 好像是只有帖子本身支持 markdown,但是回复贴不支持。
    zouzou0208
        26
    zouzou0208  
       Aug 19, 2021
    @lizytalk [sum(i[1]) for i in groupby(x, key=lambda _: _ > 0)]
    hahastudio
        27
    hahastudio  
       Aug 19, 2021
    可不可以有 0 ?有的话 0 怎么算?是继续还是单独算?
    gist.github.com/hahastudio/ec6c851a67c714ac40cf406a2aeeb525
    laduary
        28
    laduary  
       Aug 19, 2021
    用 arr[idx] * arr[idx -1] 判断正负
    https://paste.ubuntu.com/p/gpFNhcPwYm/
    mxT52CRuqR6o5
        29
    mxT52CRuqR6o5  
       Aug 19, 2021 via Android
    随便写写都是 o(n),都差不多的
    0ZXYDDu796nVCFxq
        30
    0ZXYDDu796nVCFxq  
       Aug 19, 2021 via Android
    @hahastudio 0 其实不影响结果
    zxCoder
        31
    zxCoder  
       Aug 19, 2021
    怎么个高效法。。。。
    yinheli
        32
    yinheli  
       Aug 19, 2021
    @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  
       Aug 20, 2021
    在 C++ 里面我就 i=0; j=0 开始原地求和,最后设一下 size,最高效。
    lixiang2017
        34
    lixiang2017  
       Aug 20, 2021 via Android
    说一下题外话。建议多刷题,这种在力扣属于 easy
    msg7086
        35
    msg7086  
       Aug 20, 2021
    @fkdtz 回帖啥时候有 markdown 的。
    2i2Re2PLMaDnghL
        36
    2i2Re2PLMaDnghL  
       Aug 20, 2021
    @lizytalk 这并不 pythonic,这是 functional
    不过 list(map(...)) 都可以轻易地改成 comprehension list
    yucongo
        37
    yucongo  
       Aug 20, 2021
    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  
       Aug 20, 2021
    @msg7086 肉眼 markdown
    rudy1224
        39
    rudy1224  
       Aug 21, 2021   1
    把目前回帖里面的方法对比了一下,加上了使用 NumPy+Numba 的数据:


    代码在此:
    <script src="https://gist.github.com/luhuidi/77ec31edfece0412d0058601e0f1a1ce.js"></script>
    imn1
        40
    imn1  
       Aug 26, 2021
    代码我就懒得写了,楼上很多 for 都能搞定,我给另一个解法:
    itertools.groupby,把连续+/-的分组,然后每组 sum 就是了,代码少很多,应该两三行就够了
    imn1
        41
    imn1  
       Aug 26, 2021
    呃,原来有人说了,漏看了,pass
    About     Help     Advertise     Blog     API     FAQ     Solana     2481 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 86ms UTC 15:42 PVG 23:42 LAX 08:42 JFK 11:42
    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