Somma un elenco di numeri in Python


367

Ho un elenco di numeri come [1,2,3,4,5...], e voglio calcolare (1+2)/2e per il secondo, (2+3)/2il terzo (3+4)/2e così via. Come lo posso fare?

Vorrei sommare il primo numero con il secondo e dividerlo per 2, quindi sommare il secondo con il terzo e dividere per 2 e così via.

Inoltre, come posso sommare un elenco di numeri?

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

È:

b = sum(a)
print b

ottenere un numero?

Questo non funziona per me.


Quanto dura questa lista? quanto sono casuali i valori, tra 0 e 1?
kevpie il

2
se definisci sum prima che possa rovinare Python, prova a del sum. forse è stato definito da qualche parte nel codice e sovrascrive la funzione predefinita. Quindi l'ho eliminato e il problema è stato risolto. (risposta di user4183543)
NicoKowe

1
"Questo non funziona" non è una descrizione del problema.
Marchese di Lorne,

Risposte:


279

Domanda 1: Quindi vuoi (elemento 0 + elemento 1) / 2, (elemento 1 + elemento 2) / 2, ... ecc.

Facciamo due elenchi: uno per ogni elemento tranne il primo e uno per ogni elemento tranne l'ultimo. Quindi le medie che vogliamo sono le medie di ciascuna coppia prese dalle due liste. Usiamo zipper prendere coppie da due liste.

Presumo che tu voglia vedere i decimali nel risultato, anche se i tuoi valori di input sono numeri interi. Per impostazione predefinita, Python esegue la divisione intera: scarta il resto. Per dividere le cose fino in fondo, dobbiamo usare numeri in virgola mobile. Fortunatamente, dividere un int per un float produrrà un float, quindi usiamo solo 2.0per il nostro divisore invece di 2.

Così:

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

Domanda 2:

Quell'uso di sumdovrebbe funzionare bene. Le seguenti opere:

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

Inoltre, non è necessario assegnare tutto a una variabile in ogni fase del percorso. print sum(a)funziona benissimo.

Dovrai essere più preciso su ciò che hai scritto e su come non funziona.


non ho capito, per la prima domanda ho indefinito il mio elenco. Nel mio programma è un numero casuale non 1, 2, 3, 4 .. per la seconda domanda non funziona con me non so perché
layo

37
my_listè definito solo se lo definisci. Doveva essere un segnaposto per qualunque cosa tu chiamassi la lista con cui stai cercando di lavorare. Non riesco a indovinare come lo hai chiamato.
Karl Knechtel,

2
6 anni dopo, questo post aiuta ancora le persone. Ho avuto un problema tecnico nel mio codice e sono stato in grado di utilizzare il tuo post per confermare che anche i concetti correlati nel mio codice al tuo erano corretti, quindi il problema deve trovarsi altrove. Poi l'ho trovato. Ho appena dato a te e alla persona con la domanda un voto positivo come ringraziamento. Auguri.
TMWP

1
@KarlKnechtel Aveva un elenco nella sua domanda e si chiamava " a".
Ciao Arrivederci

1
Poiché si zipferma una volta che raggiunge la fine dell'argomento più breve, zip(my_list, my_list[1:])è sufficiente.
Chepner,

115

Elenco sommario dei numeri:

sum(list_of_nums)

Calcolo della metà di n e n - 1 (se ho il modello corretto), usando una comprensione della lista :

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

Somma elementi adiacenti, ad es. ((1 + 2) / 2) + ((2 + 3) / 2) + ... usando riduci e lambda

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

4
Penso che voglia sommare gli elementi adiacenti. Non avrebbe senso prendere la media di xe x - 1; potremmo semplicemente sottrarre 0,5 invece.
Karl Knechtel,

4
La funzione di riduzione non fa ciò che dice il post. Calcola (((a1 + a2) / 2 + a3) / 2 + a4) / 2 ...
Moberg,

from functools import reduce
tyrex,

70

Domanda 2: per sommare un elenco di numeri interi:

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

Se l'elenco contiene numeri interi come stringhe:

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

4
sum(i for i in a)è semplicemente ridondante.
Jean-François Fabre

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

34

Puoi provare in questo modo:

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
non c'è bisogno di crearne una copia in questo modo, ed è terribilmente non sincero. Evita come la peste nonostante tutti i voti ...
Jean-François Fabre

@ Jean-FrançoisFabre potresti per favore dettagliare il tuo commento? Perché questo è "orribilmente non meccanico"?
PierreF,

per cominciare a[0:len(a)]crea una copia di a, qual è il punto oltre a sprecare CPU e memoria? quindi print(sm)funziona anche in Python 2. Non capisco perché questo abbia così tanti voti positivi a metà 2017 ... ma si applica alla maggior parte delle risposte qui.
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

Sembra che sumsia stato definito da qualche parte nel codice e sovrascrive la funzione predefinita. Quindi l'ho eliminato e il problema è stato risolto.


16

Utilizzando un semplice list-comprehensione il sum:

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

4
Non hai bisogno di usare [e ], puoi semplicemente passare l'espressione del generatoresum(i/2. for i in range(x))
Ivan

1
sum(range(x)) / 2.evita tutte le divisioni, basta dividere alla fine.
Jean-François Fabre

13

Tutte le risposte hanno mostrato un approccio programmatico e generale. Suggerisco un approccio matematico specifico per il tuo caso. Può essere più veloce in particolare per elenchi lunghi. Funziona perché il tuo elenco è un elenco di numeri naturali fino a n:

Supponiamo di avere i numeri naturali 1, 2, 3, ..., 10:

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

È possibile utilizzare la sumfunzione in un elenco:

>>> print sum(nat_seq)
55

Puoi anche usare la formula n*(n+1)/2dove si ntrova il valore dell'ultimo elemento nell'elenco (qui nat_seq[-1]:), in modo da evitare iterazioni sugli elementi:

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

Per generare la sequenza (1+2)/2, (2+3)/2, ..., (9+10)/2è possibile utilizzare un generatore e la formula (2*k-1)/2.(notare il punto per rendere i valori in virgola mobile). Devi saltare il primo elemento quando generi il nuovo elenco:

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

Anche qui puoi usare la sumfunzione in quell'elenco:

>>> print sum(new_seq)
49.5

Ma puoi anche usare la formula (((n*2+1)/2)**2-1)/2, in modo da evitare di ripetere gli elementi:

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

6

Il modo più semplice per risolvere questo problema:

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

4

Questa domanda ha ricevuto risposta qui

a = [1,2,3,4] sum (a) restituisce 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

I generatori sono un modo semplice per scrivere questo:

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]

Puoi anche dividere per 2.0 per evitare la divisione di numeri interi.
Chris Anderson,

@ChrisAnderson non è vero in Python 3. La divisione in virgola mobile è l'impostazione predefinita.
Justin Meiners,

3

Rendiamolo facile per il principiante: -

  1. La globalparola chiave consentirà di assegnare il messaggio della variabile globale all'interno della funzione principale senza produrre una nuova variabile locale
    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

Questo concetto si chiama Shadowing

  1. Somma un elenco di numeri 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()

Uscite = 15


2

Utilizzando la pairwise ricetta 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

Breve e semplice:

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

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

Ed ecco come appare:

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

A causa di alcuni stupidità nel modo in cui Python gestisce un mappiù di due liste, si ha a troncare la lista, a[:-1]. Funziona di più come ti aspetteresti se usi 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]

Insomma, si. Semplice? Richiede una spiegazione più lunga delle lunghe soluzioni per capire cosa sta facendo.
tekHedd

questo introduce un errore di accumulo in virgola mobile. Dividi invece alla fine.
Jean-François Fabre

1
@ Jean-FrançoisFabre Entrambi i metodi sono imperfetti - la divisione alla fine traboccerà per grandi numeri, la soluzione dipende dai dati (e dal caso d'uso).
CZ

2

Tante soluzioni, ma il mio preferito manca ancora:

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

un array numpy non è troppo diverso da un elenco (in questo caso d'uso), tranne per il fatto che è possibile trattare array come numeri:

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

Fatto!

spiegazione

Gli indici fantasia significano questo: [1:]include tutti gli elementi da 1 alla fine (omettendo così l'elemento 0), e [:-1]sono tutti gli elementi tranne l'ultimo:

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

Quindi l'aggiunta di questi due ti dà un array composto da elemens (1 + 2), (2 + 3) e così via. Non che io stia dividendo 2.0, non 2perché altrimenti Python crede che tu stia usando solo numeri interi e produca risultati interi arrotondati.

vantaggio di usare numpy

Numpy può essere molto più veloce dei cicli attorno agli elenchi di numeri. A seconda della grandezza della tua lista, molti ordini di grandezza sono più veloci. Inoltre, è molto meno codice e, almeno per me, è più facile da leggere. Sto cercando di prendere l'abitudine di usare numpy per tutti i gruppi di numeri, ed è un enorme miglioramento per tutti i loop e i loop all'interno dei loop che altrimenti avrei dovuto fare.


1

Vorrei solo usare un lambda con 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

Uso un whileloop per ottenere il risultato:

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

1

Scorri gli elementi nell'elenco e aggiorna il totale in questo modo:

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

1

Grazie a Karl Knechtel sono stato in grado di capire la tua domanda. La mia interpretazione:

  1. Volete un nuovo elenco con la media dell'elemento i e i + 1.
  2. Si desidera sommare ciascun elemento nell'elenco.

Prima domanda utilizzando la funzione anonima (aka. Funzione 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

Seconda domanda anche utilizzando la funzione anonima (aka. Funzione Lambda):

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

Entrambe le domande combinate in un'unica riga di codice:

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

usa quello più adatto alle tue esigenze


1

Puoi anche fare lo stesso usando la ricorsione:

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

Prova a utilizzare una comprensione dell'elenco. Qualcosa di simile a:

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

@Rafe è funzionante (se alla fine dovessimo solo correggere le parentesi - dovrebbe essere range(len(old_list) - 1)), ma i pitonisti generalmente disapprovano la combinazione di 'range' e 'len'. Un corollario di "dovrebbe esserci solo un modo per farlo" è "la libreria standard fornisce un modo per evitare cose brutte". Iterazione indiretta - iterare su una sequenza di numeri, in modo che tu possa usare quei numeri per indicizzare ciò su cui vuoi veramente iterare - è una cosa brutta.
Karl Knechtel,

0

Nello spirito degli itertools. Ispirazione dalla ricetta a coppie.

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

Esempi:

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

Un modo semplice è usare la permutazione 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)

Il risultato è:

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

Nota che l'ordine conta: il significato 1, 2, 7 viene mostrato anche come 2, 1, 7 e 7, 1, 2. Puoi ridurlo usando un set.


0

In Python 3.8, è possibile utilizzare il nuovo operatore di assegnazione

>>> 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è un riferimento in esecuzione al valore precedente nell'elenco, quindi viene inizializzato al primo elemento dell'elenco e l'iterazione si verifica sul resto dell'elenco, aggiornandosi adopo essere stata utilizzata in ogni iterazione.

Un iteratore esplicito viene utilizzato per evitare la necessità di creare una copia dell'elenco utilizzando my_list[1:].


-3

Prova quanto segue:

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
Una nuova risposta dovrebbe essere davvero distintamente diversa dalle risposte esistenti. Inoltre, la tua sumfunzione non differisce dal sumcomportamento o dal nome integrati . Potresti effettivamente eliminare la definizione della funzione dalla tua risposta e funzionerebbe comunque.
Noumenon,

puoi per favore controlla ora
Sai G

2
Apprezzo che stai migliorando la tua risposta! I nomi delle variabili sono più descrittivi e non ombreggiano i built-in. Ma i problemi fondamentali sono ancora lì: l'approccio for-loop è già stato fornito da stackoverflow.com/a/35359188/733092 sopra e la funzione è ridondante con il built-in sum. Otterresti una A su un test per rispondere correttamente alla domanda, ma le risposte StackOverflow devono anche essere utili alle persone che arrivano in questa pagina, e le risposte duplicate no.
Noumenon,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.