Soma uma lista de números em Python


367

Eu tenho uma lista de números como [1,2,3,4,5...], e quero calcular (1+2)/2e para o segundo (2+3)/2e o terceiro (3+4)/2, e assim por diante. Como eu posso fazer isso?

Gostaria de somar o primeiro número com o segundo e dividi-lo por 2, depois somar o segundo com o terceiro e dividir por 2, e assim por diante.

Além disso, como posso somar uma lista de números?

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

É isso:

b = sum(a)
print b

obter um número?

Isso não funciona para mim.


Quanto tempo dura essa lista? quão aleatórios são os valores, entre 0 e 1?
Kevpie

2
se você definir soma antes que ele possa atrapalhar o python, tente del sum. talvez tenha sido definido no código em algum lugar e substitua a função padrão. Então eu apaguei e o problema foi resolvido. (resposta pelo usuário4183543)
NicoKowe 6/02/19

11
"Isso não funciona" não é uma descrição do problema.
Marquês de Lorne

Respostas:


279

Pergunta 1: Então você deseja (elemento 0 + elemento 1) / 2, (elemento 1 + elemento 2) / 2, ... etc.

Fazemos duas listas: uma de cada elemento, exceto o primeiro, e uma de cada elemento, exceto o último. Então as médias que queremos são as médias de cada par extraído das duas listas. Nós usamos zippares de duas listas.

Suponho que você queira ver decimais no resultado, mesmo que seus valores de entrada sejam inteiros. Por padrão, o Python faz divisão inteira: descarta o restante. Para dividir as coisas, precisamos usar números de ponto flutuante. Felizmente, dividir um int por um float produzirá um float; portanto, usamos apenas 2.0para o nosso divisor em vez de 2.

Portanto:

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

Questão 2:

Esse uso de sumdeve funcionar bem. Os seguintes trabalhos:

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

Além disso, você não precisa atribuir tudo a uma variável a cada passo do caminho. print sum(a)funciona muito bem.

Você precisará ser mais específico sobre exatamente o que escreveu e como não está funcionando.


eu não recebi, na primeira pergunta eu tenho o my_list indefinido. No meu programa é um número aleatório não de 1, 2, 3, 4 .. para a segunda I't questão não funciona comigo Eu não sei por que
Layo

37
my_listé definido apenas se você o definir. Isso deveria ser um espaço reservado para o que você chamou de lista com a qual está tentando trabalhar. Não consigo adivinhar o que você chamou.
Karl Knechtel

2
6 anos depois, este post ainda está ajudando as pessoas. Tive uma falha no meu código e pude usar sua postagem para confirmar que os conceitos relacionados no meu código para o seu também estavam corretos, portanto, o problema deve estar em outro lugar. Então eu encontrei. Apenas dei a você e à pessoa com a pergunta um voto positivo como um agradecimento rápido. Muitas felicidades.
TMWP 17/03/2019

11
@KarlKnechtel Ele tinha uma lista em sua pergunta e chamava-se " a".
HelloGoodbye 01/08/19

11
Como zippara quando chega ao final do argumento mais curto, zip(my_list, my_list[1:])é suficiente.
chepner

115

Soma da lista de números:

sum(list_of_nums)

Calculando metade de n e n - 1 (se eu tiver o padrão correto), usando uma compreensão de lista :

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

Soma elementos adjacentes, por exemplo, ((1 + 2) / 2) + ((2 + 3) / 2) + ... usando reduzir e lambdas

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

4
Eu acho que ele quer somar elementos adjacentes. Não faria sentido tomar a média de xe x - 1; podemos apenas subtrair 0,5.
Karl Knechtel

4
A função de redução não faz o que a postagem diz. Ele calcula (((a1 + a2) / 2 + a3) / 2 + a4) / 2 ... #
6565 Moberg

from functools import reduce
Tyrex 26/12/18

70

Pergunta 2: Para somar uma lista de números inteiros:

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

Se a lista contiver números inteiros como seqüências de caracteres:

a = ['5', '6']
# import Decimal: from decimal import Decimal
sum(Decimal(i) for i in a)

4
sum(i for i in a)é apenas redundante.
Jean-François Fabre

6
sum(Decimal(i) for i in a)=> sum(int(i) for i in a)ousum(map(int,a))
Jean-François Fabre

34

Você pode tentar desta maneira:

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
não é necessário criar uma cópia como essa, e é terrivelmente não-tônico. Evite como a praga, apesar de todos os votos ...
Jean-François Fabre

@ Jean-FrançoisFabre, você poderia por favor detalhar seu comentário? Por que isso é "terrivelmente antitônico"?
31419 PierreFreel

para iniciantes a[0:len(a)]cria uma cópia de a, qual é o objetivo além de desperdiçar CPU e memória? então print(sm)também funciona no python 2. Não entendo por que isso tem tantos votos positivos em meados de 2017 ... mas se aplica à maioria das respostas aqui.
Jean-François Fabre

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

Parece que sumfoi definido no código em algum lugar e substitui a função padrão. Então eu apaguei e o problema foi resolvido.


16

Usando um simples list-comprehensione o sum:

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

4
Você não precisa usar [e ], você pode apenas passar o gerador de expressãosum(i/2. for i in range(x))
Ivan

11
sum(range(x)) / 2.evita todas as divisões, basta dividir no final.
Jean-François Fabre

13

Todas as respostas mostraram uma abordagem programática e geral. Sugiro uma abordagem matemática específica para o seu caso. Pode ser mais rápido, em especial para listas longas. Funciona porque sua lista é uma lista de números naturais até n:

Vamos supor que temos os números naturais 1, 2, 3, ..., 10:

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

Você pode usar a sumfunção em uma lista:

>>> print sum(nat_seq)
55

Você também pode usar a fórmula n*(n+1)/2onde nestá o valor do último elemento na lista (aqui nat_seq[-1]:), para evitar a iteração sobre os elementos:

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

Para gerar a sequência, (1+2)/2, (2+3)/2, ..., (9+10)/2você pode usar um gerador e a fórmula (2*k-1)/2.(observe o ponto para tornar os valores pontos flutuantes). Você precisa pular o primeiro elemento ao gerar a nova lista:

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

Aqui também, você pode usar a sumfunção nessa lista:

>>> print sum(new_seq)
49.5

Mas você também pode usar a fórmula (((n*2+1)/2)**2-1)/2, para evitar a iteração sobre os elementos:

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

6

A maneira mais simples de resolver esse problema:

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

4

Esta pergunta foi respondida aqui

a = [1,2,3,4] soma (a) retorna 10


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

Os geradores são uma maneira fácil de escrever isso:

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]

Você também pode dividir por 2,0 para evitar a divisão inteira.
Chris Anderson

@ChrisAnderson não é verdadeiro no python 3. a divisão de ponto flutuante é o padrão.
Justin Meiners

3

Vamos facilitar para o Iniciante: -

  1. A globalpalavra-chave permitirá que a mensagem da variável global seja atribuída na função principal sem produzir uma nova variável local
    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

Esse conceito é chamado de sombreamento

  1. Soma uma lista de números em 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()

Saídas = 15


2

Usando a pairwise receita de 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

Curto e simples:

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

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

E aqui está como fica:

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

Devido a alguma estupidez em como o Python lida com mapmais de duas listas, você precisa truncar a lista a[:-1],. Funciona mais como você esperaria se você usasse 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]

Curto, sim. Simples? Requer uma explicação mais longa que as longas soluções para entender o que está fazendo.
precisa saber é o seguinte

isso introduz um erro de acumulação de ponto flutuante. Divida no final.
Jean-François Fabre

11
@ Jean-FrançoisFabre Ambos os métodos são imperfeitos - a divisão no final transbordará para grandes números, a solução depende dos dados (e do caso de uso).
CZ

2

Tantas soluções, mas o meu favorito ainda está faltando:

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

uma matriz numpy não é muito diferente de uma lista (nesse caso de uso), exceto que você pode tratar matrizes como números:

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

Feito!

explicação

Os índices extravagantes significam o seguinte: [1:]inclui todos os elementos de 1 até o final (omitindo, assim, o elemento 0) e [:-1]são todos os elementos, exceto o último:

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

Portanto, a adição desses dois fornece uma matriz composta por elemens (1 + 2), (2 + 3) e assim por diante. Não que eu esteja dividindo 2.0, não 2porque de outra forma o Python acredita que você está usando apenas números inteiros e produz resultados inteiros arredondados.

vantagem de usar numpy

Numpy pode ser muito mais rápido do que fazer laços nas listas de números. Dependendo do tamanho da sua lista, várias ordens de magnitude são mais rápidas. Além disso, é muito menos código e, pelo menos para mim, é mais fácil de ler. Estou tentando criar o hábito de usar numpy para todos os grupos de números, e é uma grande melhoria para todos os loops e loops dentro de loops que eu teria que fazer.


1

Eu apenas usaria um lambda com 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

Eu uso um whileloop para obter o resultado:

i = 0
while i < len(a)-1:
   result = (a[i]+a[i+1])/2
   print result
   i +=1

1

Faça um loop pelos elementos da lista e atualize o total da seguinte maneira:

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

1

Graças a Karl Knechtel, consegui entender sua pergunta. Minha interpretação:

  1. Você deseja uma nova lista com a média do elemento iei + 1.
  2. Você deseja somar cada elemento da lista.

Primeira pergunta usando a função anônima (também conhecida como função 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

Segunda pergunta também usando a função anônima (também conhecida como função Lambda):

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

Ambas as perguntas combinadas em uma única linha de código:

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 aquele que melhor se adapte às suas necessidades


1

Você também pode fazer o mesmo usando a recursão:

Snippet do 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

Tente usar uma lista de compreensão. Algo como:

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

@ Rafe é um trabalho (se apenas corrigirmos os parênteses no final - deveria ser range(len(old_list) - 1)), mas os Pythonistas geralmente desaprovam a combinação de 'range' e 'len'. Um corolário de "deve haver apenas uma maneira de fazê-lo" é "a biblioteca padrão fornece uma maneira de evitar coisas feias". A iteração indireta - repetindo uma sequência de números, para que você possa usá-los para indexar o que realmente deseja repetir - é uma coisa feia.
Karl Knechtel

0

No espírito de ferramentas. Inspiração da receita aos pares.

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

Exemplos:

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

Uma maneira simples é usar a permutação 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)

O resultado é:

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

Observe que a ordem é importante - o que significa 1, 2, 7 também é mostrado como 2, 1, 7 e 7, 1, 2. Você pode reduzir isso usando um conjunto.


0

No Python 3.8, o novo operador de atribuição pode ser usado

>>> 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é uma referência em execução ao valor anterior na lista; portanto, ele é inicializado no primeiro elemento da lista e a iteração ocorre no restante da lista, atualizando aapós o uso em cada iteração.

Um iterador explícito é usado para evitar a necessidade de criar uma cópia da lista usando my_list[1:].


-3

Tente o seguinte -

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
Uma nova resposta deve realmente ser distintamente diferente das respostas existentes. Além disso, sua sumfunção não difere do sumcomportamento ou nome interno. Você pode realmente excluir a definição da função da sua resposta e ela ainda funcionaria.
Noumenon

você pode, por favor, verifique agora
Sai G

2
Compreendo que você esteja melhorando sua resposta! Os nomes das variáveis ​​são mais descritivos e não sombreiam os incorporados. Mas os problemas fundamentais ainda estão lá: a abordagem de loop for já foi fornecida por stackoverflow.com/a/35359188/733092 acima e a função é redundante com a incorporada sum. Você recebe um A em um teste para responder à pergunta corretamente, mas as respostas do StackOverflow também precisam ser úteis para as pessoas que chegam a esta página e as respostas duplicadas não.
Noumenon
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.