444

Given a list of numbers such as:

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

How do I calculate their total sum:

1 + 2 + 3 + 4 + 5 + ...

How do I calculate their pairwise averages:

[(1+2)/2, (2+3)/2, (3+4)/2, (4+5)/2, ...]
Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
layo
  • 4,489
  • 2
  • 15
  • 3

26 Answers26

356
Question 1:

To sum a list of numbers, use sum:

xs = [1, 2, 3, 4, 5]
print(sum(xs))

This outputs:

15

Question 2:

So you want (element 0 + element 1) / 2, (element 1 + element 2) / 2, ... etc.

We make two lists: one of every element except the first, and one of every element except the last. Then the averages we want are the averages of each pair taken from the two lists. We use zip to take pairs from two lists.

I assume you want to see decimals in the result, even though your input values are integers. By default, Python does integer division: it discards the remainder. To divide things through all the way, we need to use floating-point numbers. Fortunately, dividing an int by a float will produce a float, so we just use 2.0 for our divisor instead of 2.

Thus:

averages = [(x + y) / 2.0 for (x, y) in zip(my_list[:-1], my_list[1:])]
Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
  • 4
    Since `zip` stops once it reaches the end of the shorter argument, `zip(my_list, my_list[1:])` is sufficient. – chepner Dec 04 '19 at 19:08
  • Yes, and that's how I usually see it written; stylistically I prefer the symmetry of slicing both, although it's less efficient. – Karl Knechtel Dec 07 '19 at 09:20
  • I swapped the order of the [sub-questions](https://meta.stackexchange.com/questions/39223/one-post-with-multiple-questions-or-multiple-posts) to make this more useful for the most common case that most beginners are searching for. Also, the question/top answer have 2 million views but very few upvotes in comparison to other popular questions (that have 10x the upvotes!). Perhaps this is an indication that the less common "sub-question" should be removed altogether. Do you agree with this? – Mateen Ulhaq Aug 15 '22 at 06:57
  • @MateenUlhaq please take this issue to [Meta](https://meta.stackoverflow.com). My first reaction is that I agree, but this needs to be discussed. – Karl Knechtel Aug 15 '22 at 07:08
  • @MateenUlhaq even a very low scoring, unpopular question is better to use as the canonical if it meets standards while this one does not (it is clearly two completely unrelated questions, and thus "needs more focus"). The best I've found specifically for the `sum` question so far (i.e., without introducing any other weird requirements such as converting strings to integers - i.e. https://stackoverflow.com/questions/11344827/summing-elements-in-a-list is **not** good enough) is https://stackoverflow.com/questions/17472771/how-to-sum-a-list-of-numbers-in-python; but I will keep looking. – Karl Knechtel Sep 08 '22 at 08:29
  • Despite how it was initially received, https://stackoverflow.com/questions/13909052/how-do-i-add-together-integers-in-a-list-in-python might be better. – Karl Knechtel Sep 08 '22 at 08:42
144

To sum a list of numbers:

sum(list_of_nums)

Generate a new list with adjacent elements averaged in xs using a list comprehension:

[(x + y) / 2 for x, y in zip(xs, xs[1:])]

Sum all those adjacent elements into a single value:

sum((x + y) / 2 for x, y in zip(xs, xs[1:]))
Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
Rafe Kettler
  • 75,757
  • 21
  • 156
  • 151
79

Question 2: To sum a list of integers:

a = [2, 3, 5, 8]
sum(a)
# 18
# or you can do:
sum(i for i in a)
# 18

If the list contains integers as strings:

a = ['5', '6']
# import Decimal: from decimal import Decimal
sum(Decimal(i) for i in a)
Evans Murithi
  • 3,197
  • 1
  • 21
  • 26
36

You can try this way:

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
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Md. Rezwanul Haque
  • 2,882
  • 7
  • 28
  • 45
  • 6
    no need to create a copy like this, and it's horribly unpythonic. Avoid like the plague despite all the votes... – Jean-François Fabre Apr 18 '18 at 13:41
  • @Jean-FrançoisFabre could you please details your comment ? Why is this "horribly unpythonic" ? – Pierre Nov 13 '19 at 15:51
  • 2
    for starters `a[0:len(a)]` creates a copy of `a`, what's the point besides wasting CPU & memory? then `print(sm)` also works in python 2. I don't understand why this has so many upvotes in mid-2017... but it applies to most of the answers here. – Jean-François Fabre Nov 13 '19 at 16:15
28
>>> 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

It seems that sum has been defined in the code somewhere and overwrites the default function. So I deleted it and the problem was solved.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
user4183543
  • 329
  • 3
  • 2
18

This question has been answered here

a = [1,2,3,4]
sum(a) 

sum(a) returns 10

Vijay
  • 1,030
  • 11
  • 34
16

Using a simple list-comprehension and the sum:

>> sum(i for i in range(x))/2. #if x = 10 the result will be 22.5
Shapi
  • 5,493
  • 4
  • 28
  • 39
14

All answers did show a programmatic and general approach. I suggest a mathematical approach specific for your case. It can be faster in particular for long lists. It works because your list is a list of natural numbers up to n:

Let's assume we have the natural numbers 1, 2, 3, ..., 10:

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

You can use the sum function on a list:

>>> print sum(nat_seq)
55

You can also use the formula n*(n+1)/2 where n is the value of the last element in the list (here: nat_seq[-1]), so you avoid iterating over elements:

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

To generate the sequence (1+2)/2, (2+3)/2, ..., (9+10)/2 you can use a generator and the formula (2*k-1)/2. (note the dot to make the values floating points). You have to skip the first element when generating the new list:

>>> 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]

Here too, you can use the sum function on that list:

>>> print sum(new_seq)
49.5

But you can also use the formula (((n*2+1)/2)**2-1)/2, so you can avoid iterating over elements:

>>> print (((new_seq[-1]*2+1)/2)**2-1)/2
49.5
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ely
  • 10,860
  • 4
  • 43
  • 64
6

The simplest way to solve this problem:

l =[1,2,3,4,5]
sum=0
for element in l:
    sum+=element
print sum
Toby Speight
  • 27,591
  • 48
  • 66
  • 103
shashankS
  • 1,043
  • 1
  • 11
  • 21
6

So many solutions, but my favourite is still missing:

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

a numpy array is not too different from a list (in this use case), except that you can treat arrays like numbers:

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

Done!

explanation

The fancy indices mean this: [1:] includes all elements from 1 to the end (thus omitting element 0), and [:-1] are all elements except the last one:

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

So adding those two gives you an array consisting of elements (1+2), (2+3) and so on. Note that I'm dividing by 2.0, not 2 because otherwise Python believes that you're only using integers and produces rounded integer results.

advantage of using numpy

Numpy can be much faster than loops around lists of numbers. Depending on how big your list is, several orders of magnitude faster. Also, it's a lot less code, and at least to me, it's easier to read. I'm trying to make a habit out of using numpy for all groups of numbers, and it is a huge improvement to all the loops and loops-within-loops I would otherwise have had to write.

Zak
  • 3,063
  • 3
  • 23
  • 30
4

Using the pairwise itertools recipe:

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) )
tzot
  • 92,761
  • 29
  • 141
  • 204
  • 1
    As of Python 3.10, this is now [built-in](https://docs.python.org/3/library/itertools.html#itertools.pairwise): `from itertools import pairwise` is enough. – tlgs Jan 28 '22 at 17:40
3

Generators are an easy way to write this:

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]
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Jochen Ritzel
  • 104,512
  • 31
  • 200
  • 194
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]
tagoma
  • 3,896
  • 4
  • 38
  • 57
3

Let us make it easy for Beginner:-

  1. The global keyword will allow the global variable message to be assigned within the main function without producing a new local variable
    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

This concept is called Shadowing

  1. Sum a list of numbers in 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()

Outputs = 15

Aamir M Meman
  • 1,645
  • 14
  • 15
3

In Python 3.8, the new assignment operator can be used

>>> 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 is a running reference to the previous value in the list, hence it is initialized to the first element of the list and the iteration occurs over the rest of the list, updating a after it is used in each iteration.

An explicit iterator is used to avoid needing to create a copy of the list using my_list[1:].

chepner
  • 497,756
  • 71
  • 530
  • 681
2

Short and simple:

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

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

And here's how it looks:

>>> 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]

Due to some stupidity in how Python handles a map over two lists, you do have to truncate the list, a[:-1]. It works more as you'd expect if you use 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]
Michael J. Barber
  • 24,518
  • 9
  • 68
  • 88
  • Short, yes. Simple? It requires an explanation longer than the long solutions to understand what it's doing. – tekHedd Mar 01 '17 at 17:47
  • this introduces floating point accumulation error. Divide in the end instead. – Jean-François Fabre Apr 18 '18 at 13:42
  • 1
    @Jean-FrançoisFabre Both methods are imperfect - dividing at the end will overflow for large numbers, the solution depends on the data (and the use case). – c z Dec 10 '19 at 10:07
2

You can also do the same using recursion:

Python Snippet:

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))
vijayraj34
  • 2,135
  • 26
  • 27
1

I use a while loop to get the result:

i = 0
while i < len(a)-1:
   result = (a[i]+a[i+1])/2
   print result
   i +=1
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Aashutosh jha
  • 552
  • 6
  • 8
1

In the spirit of itertools. Inspiration from the pairwise recipe.

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))

Examples:

>>>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]
kevpie
  • 25,206
  • 2
  • 24
  • 28
1

Loop through elements in the list and update the total like this:

def sum(a):
    total = 0
    index = 0
    while index < len(a):
        total = total + a[index]
        index = index + 1
    return total
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
1

Thanks to Karl Knechtel i was able to understand your question. My interpretation:

  1. You want a new list with the average of the element i and i+1.
  2. You want to sum each element in the list.

First question using anonymous function (aka. Lambda function):

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

Second question also using anonymous function (aka. Lambda function):

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

Both questions combined in a single line of code :

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

use the one that fits best your needs

StickySli
  • 81
  • 8
0

I'd just use a lambda with 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
Orane
  • 2,223
  • 1
  • 20
  • 33
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)
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
0

Try using a list comprehension. Something like:

new_list = [(old_list[i] + old_list[i+1])/2 for i in range(len(old_list-1))]
TartanLlama
  • 63,752
  • 13
  • 157
  • 193
  • @Rafe it's a *working* one (if we just fix the parentheses at the end - should be `range(len(old_list) - 1)`), but Pythonistas generally frown upon the combination of 'range' and 'len'. A corollary to "there should only be one way to do it" is "the standard library provides a way for you to avoid ugly things". Indirect iteration - iterating over a sequence of numbers, so that you can use those numbers to index what you really want to iterate over - is an ugly thing. – Karl Knechtel Dec 06 '10 at 02:42
0

A simple way is to use the iter_tools permutation

# 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)

The result is:

[(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)]

Note that order matters - meaning 1, 2, 7 is also shown as 2, 1, 7 and 7, 1, 2. You can reduce this by using a set.

Jesse
  • 213
  • 3
  • 13
  • This answer seems to be unrelated to the question. The question has nothing to do with triples of numbers which sum to a given target. – John Coleman Jan 24 '23 at 17:09
-3

Try the following -

mylist = [1, 2, 3, 4]   

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

result = add(mylist)
print("sum = ", result)
Tushar Walzade
  • 3,737
  • 4
  • 33
  • 56
Sai G
  • 35
  • 2
  • 10
  • 2
    A new answer should really be distinctively different from the existing answers. Also, your `sum` function does not differ from the built-in `sum` in behavior or name. You could actually delete the function definition from your answer and it would still work. – Noumenon Jul 05 '16 at 17:48
  • can you please check now – Sai G Jul 05 '16 at 21:07
  • 2
    I appreciate that you're improving your answer! The variable names are more descriptive and don't shadow the built-ins. But the fundamental problems are still there: the for-loop approach was already provided by http://stackoverflow.com/a/35359188/733092 above, and the function is redundant with the built-in `sum`. You'd get an A on a test for answering the question correctly, but StackOverflow answers also need to be *useful* to people arriving at this page, and duplicate answers aren't. – Noumenon Jul 05 '16 at 21:15