【问题标题】:Subtracting Elements of List减去列表的元素
【发布时间】:2019-01-22 19:54:48
【问题描述】:

我有一个整数列表,我想以连续的顺序相互减去。我希望能够将代码用于任何大小的整数列表,即使我不知道整数的数量。

到目前为止我所做的:

a = [10, 9, 8]  # Example list with 3 integers
sub = 0
for i, n in enumerate(a):
    sub = a[i] - a[i+1]
print(sub)

我的预期答案是 -7,因为:

10 - 9 = 1

那么 1 - 8 = -7

10 和 9 分别是列表 a 的第一个和第二个元素。我减去它们得到 1。然后我取 1 并从中减去 8(列表的第三个元素)得到 -7。

相反,我收到列表索引超出范围的错误。我知道我为什么会得到这个:因为当i 命中 2 时,i+1 变为 3,并且列表中没有 a[3] 元素。

然而对于如此简单的事情,我似乎无法弄清楚如何获得这样的连续索引,尤其是对于我不知道元素数量的列表。

我该如何解决这个问题?当我得到IndexError 时,我应该只使用try-except 子句和break 吗?

【问题讨论】:

    标签: python python-3.x list loops


    【解决方案1】:

    如果您只是在整个列表的总结果之后(即[10,9,8] 的答案为-7 而不是[10, 1, -7] 的结果)那么您只需减去所有的总和第一项之后的值。减法的顺序无关紧要。

    import numpy as np
    a = [10, 9, 8]
    sub = a[0] - np.sum(a[1:])
    

    如果您想要累积结果(即[10, 1, -7] 的结果),请使用cumsum 函数:

    sub = np.append(a[0], a[0] - np.cumsum(a[1:]))
    

    【讨论】:

      【解决方案2】:
      from functools import reduce
      num=[100,20,30,12,15,10]
      print(reduce(lambda x,y:x-y,num))
      

      【讨论】:

      • 欢迎来到 Stack Overflow!纯代码答案并不是特别有用。请添加一些关于此代码如何解决问题的说明。
      【解决方案3】:

      比显式循环或reduce 更简单、更快速的解决方案:意识到a - b - c - ... - n 等效于a - (b + c + ... + n),因此您可以使用sum 函数(在C 层针对适合于C long,只有在溢出 C long 时才会退回到更昂贵的 Python 级别 ints。

      a = [10, 9, 8]  # Example list with 3 integers
      sub = a[0] - sum(a[1:])
      print(sub)
      

      注意:这会生成大部分 a 的浅拷贝,并且需要序列类型(以支持索引/切片),而不是任何可迭代的。您可以使用稍长的代码来解决这两个问题:

      a = [10, 9, 8]  # Example list with 3 integers
      aiter = iter(a)  # Make iterator from any iterable
      sub = next(aiter) - sum(aiter)  # Pull first item from iterator, then pass rest to sum
      print(sub)
      

      这对于小输入 lists 会稍微慢一些(iter/next 的固定开销略大于索引/切片的固定开销,尽管切片的复制开销会增加 @ 987654335@/next 缺少),但更长的输入所节省的成本将足以弥补它。

      【讨论】:

      • 我看到了你关于a - (b + c + ... + n) 的逻辑,这绝对是我没有考虑到的。我确实知道sum(),但想避免使用它,因为我想通过显式迭代和循环来练习一下(因为我正在尝试学习C++,我认为没有sum())。不过,我不完全理解您关于“大部分a 的浅拷贝”的观点。你的意思是当我使用sum() 时会创建一个新的list 对象并将其存储在内存中,这就是你试图用iter() 表达的意思吗?
      • @WaterGuy:不是sum 本身,而是a 上的切片操作; a[1:] 生成一个新的list,其中包含除a 的第一个元素之外的所有元素。至于“尝试学习 C++”,在 Python 中这样做并不是一个有用的开始;不同的语言有不同的优势和特点,尝试通过一种相似性非常有限的语言来学习 C++ 不会让你走得太远。至于C++和sumit's spelled std::reduce in C++17(默认归约函数是加法,变成sum函数)。 :-)
      【解决方案4】:

      根据您的预期输出 -7,您需要从当前所在元素之前的运行差异中减去,而不是 a[i] - a[i+1]

      就索引问题而言,您可以通过添加逻辑检查来解决它,通过将端点限制为len(a) - 1 来确保数组中有剩余元素

      a = [10, 9, 8]  # Example list with 3 integers
      sub = a[0]
      for i, n in enumerate(a):
          if i < (len(a) - 1):
              sub = sub - a[i + 1]
      print(sub)
      

      【讨论】:

      • 是的,我发帖后才意识到我的逻辑是错误的;我应该保持 running 的区别,而不是 consecutive 的区别。您与if 语句的行也是我正在寻找的!谢谢!
      • 注意:在每个循环上测试i &lt; len(a) - 1 是在以牺牲常见情况为代价来优化罕见情况。将循环更改为for x in a[1:]: sub -= xfor i in range(1, len(a)): sub -= a[i],或者甚至只是将循环包装在try/except IndexError: pass 中,将获得相同的效果(对除第一个以外的所有值进行操作),但开销要低得多(Python 级数学,len 检查,并且索引的开销都比您预期的要高)。
      【解决方案5】:

      您可以将functools.reduceoperator.sub 一起使用

      from operator import sub
      from functools import reduce
      
      a = [10, 9, 8]
      
      reduce(sub, a)
      # -7
      

      这大致相当于

      a = [10, 9, 8]
      
      accumulator = a[0]
      for x in a[1:]:
          accumulator -= x
      
      print(accumulator)
      # -7
      

      【讨论】:

      • 非常简洁!我听说过reduce(),但以前从未使用过!感谢分享。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-06-13
      • 1970-01-01
      • 2021-10-18
      • 1970-01-01
      • 1970-01-01
      • 2018-08-11
      • 1970-01-01
      相关资源
      最近更新 更多