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 · 3493 次点击
    这是一个创建于 974 天前的主题,其中的信息可能已经有所发展或是发生改变。

    请问如何高效计算 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:00   ❤️ 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
    zmxnv123
        12
    zmxnv123  
       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 要搞得这么难以捉摸。
    lostvincent
        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
    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),都差不多的
    gstqc
        30
    gstqc  
       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   ·   我们的愿景   ·   实用小工具   ·   934 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 19:58 · PVG 03:58 · LAX 12:58 · JFK 15:58
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.