对Python中的数字列表求和


366

我有一个数字列表,例如[1,2,3,4,5...],我想计算(1+2)/2第二个,(2+3)/2第三个, (3+4)/2等等。我怎样才能做到这一点?

我想将第一个数字与第二个数字相加并除以2,然后将第二个数字与第三个数字相加并除以2,依此类推。

另外,如何求和数字列表?

a = [1, 2, 3, 4, 5, ...]

是吗:

b = sum(a)
print b

得到一个号码?

这对我不起作用。


这个清单多久了?值在0到1之间有多随机?
kevpie 2010年

2
如果在sum可能会弄乱python之前定义了sum,请尝试del sum。也许它已经在代码中的某个地方定义并覆盖了默认功能。所以我删除了它,问题解决了。(user4183543的回答)
NicoKowe

1
“这不起作用”不是问题描述。
罗恩侯爵

Answers:


279

问题1:因此,您想要(元素0 +元素1)/ 2,(元素1 +元素2)/ 2,...等等。

我们列出两个列表:除第一个元素之外的每个元素中的一个,除最后一个元素之外的每个元素中的一个。然后,我们想要的平均值是从两个列表中得出的每对平均值。我们zip过去常常从两个列表中取对。

我假设即使输入值是整数,您也希望在结果中看到小数。默认情况下,Python会进行整数除法:它会丢弃余数。要完全划分事物,我们需要使用浮点数。幸运的是,将int除以浮点数将产生一个浮点数,因此我们仅将其2.0用作除数而不是2

从而:

averages = [(x + y) / 2.0 for (x, y) in zip(my_list[:-1], my_list[1:])]

问题2:

的使用sum应该可以正常工作。以下作品:

a = range(10)
# [0,1,2,3,4,5,6,7,8,9]
b = sum(a)
print b
# Prints 45

同样,您不需要在此过程的每一步都将所有内容分配给变量。print sum(a)效果很好。

您将必须更确切地确切地写出您所写的内容以及它是如何工作的。


我没有得到,第一个问题是我的my_list未定义。在我的程序中,它的随机数不是1、2、3、4 ..对于第二个问题,我不与我合作,我也不知道为什么
LAYO 2010年

37
my_list仅在定义时定义。无论您要使用哪个列表,都应该将其用作占位符。我猜不到你叫什么。
Karl Knechtel 2010年

2
6年后,此职位仍在为人们提供帮助。我的代码有毛刺,可以使用您的帖子来确认代码中与您有关的概念也是正确的,因此问题必须出在其他地方。然后我找到了。刚刚给您和有问题的人一个快速投票,谢谢。最好的祝愿。
TMWP

1
@KarlKnechtel他的问题中确实有一个列表,它被称为“ a”。
HelloGoodbye

1
由于zip一旦到达较短参数的结尾就停止,这就zip(my_list, my_list[1:])足够了。
chepner

114

总数列表:

sum(list_of_nums)

使用列表推导计算n和n-1的一半(如果我的模式正确):

[(x + (x - 1)) / 2 for x in list_of_nums]

对相邻元素求和,例如((1 + 2)/ 2)+((2 + 3)/ 2)+ ...使用reducelambda

reduce(lambda x, y: (x + y) / 2, list_of_nums)

4
我认为他想对相邻元素求和。会有采取的平均无点xx - 1; 我们可以减去0.5。
Karl Knechtel 2010年

4
reduce函数不执行该帖子所说的。计算((((a1 + a2)/ 2 + a3)/ 2 + a4)/ 2 ...
Moberg

from functools import reduce
tyrex


34

您可以这样尝试:

a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
sm = sum(a[0:len(a)]) # Sum of 'a' from 0 index to 9 index. sum(a) == sum(a[0:len(a)]
print(sm) # Python 3
print sm  # Python 2

4
无需创建这样的副本,这非常令人难以置信。避免类似,尽管所有的瘟疫票...
让·弗朗索瓦·法布尔

@Jean-FrançoisFabre您能否详细说明您的评论?为什么这是“令人难以置信的不可思议”?
PierreF

为初学者a[0:len(a)]创建的副本a,除了浪费CPU和内存外,还有什么意义?然后print(sm)也可以在python 2中使用。我不明白为什么在2017年中期会有如此多的投票...但是它适用于此处的大多数答案。
让·弗朗索瓦·法布尔

27
>>> a = range(10)
>>> sum(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'int' object is not callable
>>> del sum
>>> sum(a)
45

似乎sum已经在代码中的某个地方定义了该代码,并覆盖了默认功能。所以我删除了它,问题解决了。


16

使用简单list-comprehensionsum

>> sum(i for i in range(x))/2. #if x = 10 the result will be 22.5

4
您不需要使用[],您只需传递生成器表达式sum(i/2. for i in range(x))
Ivan

1
sum(range(x)) / 2.避免所有分裂,只是最后分裂。
让·弗朗索瓦·法布尔

13

所有答案均显示出程序化和通用的方法。我建议针对您的情况的数学方法。特别是对于长列表,它可能会更快。之所以有效,是因为您的列表是一个自然数列表,最多可包含n

假设我们有自然数1, 2, 3, ..., 10

>>> nat_seq = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

您可以sum在列表中使用该功能:

>>> print sum(nat_seq)
55

您还可以使用公式n*(n+1)/2where n是列表中最后一个元素的值(此处nat_seq[-1]:),因此可以避免迭代元素:

>>> print (nat_seq[-1]*(nat_seq[-1]+1))/2
55

要生成序列(1+2)/2, (2+3)/2, ..., (9+10)/2,可以使用生成器和公式(2*k-1)/2.(注意点使值成为浮点)。生成新列表时,您必须跳过第一个元素:

>>> new_seq = [(2*k-1)/2. for k in nat_seq[1:]]
>>> print new_seq
[1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5]

您也可以sum在此列表中使用该函数:

>>> print sum(new_seq)
49.5

但是您也可以使用公式(((n*2+1)/2)**2-1)/2,因此可以避免迭代元素:

>>> print (((new_seq[-1]*2+1)/2)**2-1)/2
49.5

6

解决此问题的最简单方法:

l =[1,2,3,4,5]
sum=0
for element in l:
    sum+=element
print sum


3
import numpy as np    
x = [1,2,3,4,5]
[(np.mean((x[i],x[i+1]))) for i in range(len(x)-1)]
# [1.5, 2.5, 3.5, 4.5]

3

生成器是编写此代码的简单方法:

from __future__ import division
# ^- so that 3/2 is 1.5 not 1

def averages( lst ):
    it = iter(lst) # Get a iterator over the list
    first = next(it)
    for item in it:
        yield (first+item)/2
        first = item

print list(averages(range(1,11)))
# [1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5]

您也可以除以2.0,以避免整数除法。
克里斯·安德森

@ChrisAnderson在python 3中不正确。默认是浮点除法。
贾斯汀·迈纳斯

3

让我们为初学者轻松:-

  1. global关键字将允许主函数内分配全局变量消息,而不产生新的本地变量
    message = "This is a global!"


def main():
    global message
    message = "This is a local"
    print(message)


main()
# outputs "This is a local" - From the Function call
print(message)
# outputs "This is a local" - From the Outer scope

这个概念叫做阴影

  1. 对Python中的数字列表求和
nums = [1, 2, 3, 4, 5]

var = 0


def sums():
    for num in nums:
        global var
        var = var + num
    print(var)


if __name__ == '__main__':
    sums()

输出= 15


2

使用pairwise itertools配方

import itertools
def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = itertools.tee(iterable)
    next(b, None)
    return itertools.izip(a, b)

def pair_averages(seq):
    return ( (a+b)/2 for a, b in pairwise(seq) )

2

简短:

def ave(x,y):
  return (x + y) / 2.0

map(ave, a[:-1], a[1:])

外观如下:

>>> a = range(10)
>>> map(ave, a[:-1], a[1:])
[0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5]

由于Python如何处理map两个以上的列表有些愚蠢,因此您必须截断该列表a[:-1]。如果您使用它,它的工作效果将超出您的预期itertools.imap

>>> import itertools
>>> itertools.imap(ave, a, a[1:])
<itertools.imap object at 0x1005c3990>
>>> list(_)
[0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5]

简短的,是的。简单?与长期的解决方案相比,它需要更长的解释时间以了解其工作状况。
tekHedd

这引入了浮点累积误差。最后分开。
让·弗朗索瓦·法布尔

1
@Jean-FrançoisFabre两种方法都不完美-最后分割会溢出大量,解决方案取决于数据(和用例)。
cz

2

如此众多的解决方案,但我最喜欢的仍然缺失:

>>> import numpy as np
>>> arr = np.array([1,2,3,4,5])

numpy数组与列表没有太大区别(在这种情况下),除了可以将数组视为数字:

>>> ( arr[:-1] + arr[1:] ) / 2.0
[ 1.5  2.5  3.5  4.5]

做完了!

说明

花式索引的含义是:[1:]包括从1到末尾的所有元素(因此省略元素0),并且[:-1]是除最后一个元素之外的所有元素:

>>> arr[:-1]
array([1, 2, 3, 4])
>>> arr[1:]
array([2, 3, 4, 5])

因此,将这两个元素相加即可得到一个由元素(1 + 2),(2 + 3)等组成的数组。并不是说我要除以2.0,不是2因为否则Python会认为您仅使用整数并产生四舍五入的整数结果。

使用numpy的优势

NumPy的可快于各地的号码清单循环。根据列表的大小,速度快几个数量级。而且,它的代码少得多,至少对我来说,它更易于阅读。我正在尝试养成对所有数字组都使用numpy的习惯,这对我原本必须制作的所有循环和内部循环都是一个巨大的改进。


1

我只是将lambda与map()一起使用

a = [1,2,3,4,5,6,7,8,9,10]
b = map(lambda x, y: (x+y)/2.0, fib[:-1], fib[1:])
print b


1

遍历列表中的元素并像这样更新总数:

def sum(a):
    total = 0
    index = 0
    while index < len(a):
        total = total + a[index]
        index = index + 1
    return total

1

多亏了Karl Knechtel,我才能够理解您的问题。我的解释:

  1. 您想要一个包含元素i和i + 1平均值的新列表。
  2. 您要对列表中的每个元素求和。

使用匿名函数(又名Lambda函数)的第一个问题:

s = lambda l: [(l[0]+l[1])/2.] + s(l[1:]) if len(l)>1 else []  #assuming you want result as float
s = lambda l: [(l[0]+l[1])//2] + s(l[1:]) if len(l)>1 else []  #assuming you want floor result

第二个问题也使用匿名函数(又名Lambda函数):

p = lambda l: l[0] + p(l[1:]) if l!=[] else 0

这两个问题合并在一行代码中:

s = lambda l: (l[0]+l[1])/2. + s(l[1:]) if len(l)>1 else 0  #assuming you want result as float
s = lambda l: (l[0]+l[1])/2. + s(l[1:]) if len(l)>1 else 0  #assuming you want floor result

使用最适合您需求的那个


1

您也可以使用递归进行相同的操作:

Python片段:

def sumOfArray(arr, startIndex):
    size = len(arr)
    if size == startIndex:  # To Check empty list
        return 0
    elif startIndex == (size - 1): # To Check Last Value
        return arr[startIndex]
    else:
        return arr[startIndex] + sumOfArray(arr, startIndex + 1)


print(sumOfArray([1,2,3,4,5], 0))

0

尝试使用列表理解。就像是:

new_list = [(old_list[i] + old_list[i+1])/2 for i in range(len(old_list-1))]

@Rafe是一个有效的工具(如果我们只是在结尾处纠正括号-应该是range(len(old_list) - 1)),但是Pythonista人士通常不喜欢'range'和'len'的组合。“只有一种方法可以做到”的推论是“标准库为您提供了避免丑陋事情的方法”。间接迭代-迭代一个数字序列,以便您可以使用这些数字来索引真正要迭代的对象-是一件丑陋的事情。
Karl Knechtel 2010年

0

本着itertools的精神。成对配方的灵感。

from itertools import tee, izip

def average(iterable):
    "s -> (s0,s1)/2.0, (s1,s2)/2.0, ..."
    a, b = tee(iterable)
    next(b, None)
    return ((x+y)/2.0 for x, y in izip(a, b))

例子:

>>>list(average([1,2,3,4,5]))
[1.5, 2.5, 3.5, 4.5]
>>>list(average([1,20,31,45,56,0,0]))
[10.5, 25.5, 38.0, 50.5, 28.0, 0.0]
>>>list(average(average([1,2,3,4,5])))
[2.0, 3.0, 4.0]

0
n = int(input("Enter the length of array: "))
list1 = []
for i in range(n):
    list1.append(int(input("Enter numbers: ")))
print("User inputs are", list1)

list2 = []
for j in range(0, n-1):
    list2.append((list1[j]+list1[j+1])/2)
print("result = ", list2)

0

一种简单的方法是使用iter_tools排列

# If you are given a list

numList = [1,2,3,4,5,6,7]

# and you are asked to find the number of three sums that add to a particular number

target = 10
# How you could come up with the answer?

from itertools import permutations

good_permutations = []

for p in permutations(numList, 3):
    if sum(p) == target:
        good_permutations.append(p)

print(good_permutations)

结果是:

[(1, 2, 7), (1, 3, 6), (1, 4, 5), (1, 5, 4), (1, 6, 3), (1, 7, 2), (2, 1, 7), (2, 3, 
5), (2, 5, 3), (2, 7, 1), (3, 1, 6), (3, 2, 5), (3, 5, 2), (3, 6, 1), (4, 1, 5), (4, 
5, 1), (5, 1, 4), (5, 2, 3), (5, 3, 2), (5, 4, 1), (6, 1, 3), (6, 3, 1), (7, 1, 2), 
(7, 2, 1)]

请注意,顺序很重要-意思是1、2、7也显示为2、1、7和7、1、2。您可以通过使用集合来减少此数目。


0

在Python 3.8中,可以使用新的赋值运算符

>>> my_list = [1, 2, 3, 4, 5]
>>> itr = iter(my_list)
>>> a = next(itr)
>>> [(a + (a:=x))/2 for x in itr]
[1.5, 2.5, 3.5, 4.5]

a是对列表中前一个值的运行引用,因此将其初始化为列表的第一个元素,并且迭代在列表的其余部分进行,a并在每次迭代中使用后进行更新。

显式迭代器用于避免使用创建列表的副本my_list[1:]


-3

试试以下-

mylist = [1, 2, 3, 4]   

def add(mylist):
    total = 0
    for i in mylist:
        total += i
    return total

result = add(mylist)
print("sum = ", result)

2
新答案确实应该与现有答案有明显区别。另外,您的sum功能与内置sum行为或名称没有区别。您实际上可以从答案中删除函数定义,它仍然可以使用。
Noumenon

您能现在检查一下吗
Sai G

2
感谢您改善您的答案!变量名称更具描述性,不会遮盖内置变量。但是基本问题仍然存在:for循环方法已由上述stackoverflow.com/a/35359188/733092提供,并且该功能与内置功能无关sum。您可以在测试中得到A来正确回答问题,但是StackOverflow答案对于到达此页面的人也很有用,而重复答案则不是。
Noumenon
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.