Zsumuj listę liczb w Pythonie

366

Mam listę liczb, takich jak [1,2,3,4,5...], i chcę obliczyć, (1+2)/2a dla drugiego, (2+3)/2trzeciego (3+4)/2, i tak dalej. Jak mogę to zrobić?

Chciałbym zsumować pierwszą liczbę z drugą i podzielić ją przez 2, następnie zsumować drugą liczbę z trzecią i podzielić przez 2, i tak dalej.

Jak mogę zsumować listę liczb?

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

Czy to jest:

b = sum(a)
print b

dostać jeden numer?

To mi nie działa.

layo
źródło
Jak długa jest ta lista? jak losowe są wartości od 0 do 1?
kevpie,
2
jeśli zdefiniujesz sumę, zanim będzie mógł zepsuć Pythona, spróbuj del sum. może gdzieś został zdefiniowany w kodzie i zastępuje domyślną funkcję. Więc go usunąłem i problem został rozwiązany. (odpowiedź użytkownika 4183543)
NicoKowe
1
„To nie działa” nie jest opisem problemu.
Markiz Lorne

Odpowiedzi:

279

Pytanie 1: Więc chcesz (element 0 + element 1) / 2, (element 1 + element 2) / 2, ... itd.

Tworzymy dwie listy: jedną z każdego elementu z wyjątkiem pierwszego i jedną z każdego elementu z wyjątkiem ostatniego. Następnie średnie, które chcemy, są średnimi dla każdej pary wziętej z dwóch list. Używamy zippar z dwóch list.

Zakładam, że chcesz zobaczyć dziesiętne wyniki, mimo że wartości wejściowe są liczbami całkowitymi. Domyślnie Python dokonuje podziału na liczby całkowite: odrzuca resztę. Aby podzielić wszystko na wylot, musimy użyć liczb zmiennoprzecinkowych. Na szczęście podzielenie 2.0liczby całkowitej przez liczbę zmiennoprzecinkową spowoduje utworzenie liczby zmiennoprzecinkowej, więc zamiast tego używamy po prostu naszego dzielnika 2.

A zatem:

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

Pytanie 2:

Takie użycie sumpowinno działać dobrze. Następujące prace:

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

Nie musisz też przypisywać wszystkiego do zmiennej na każdym kroku. print sum(a)działa dobrze.

Będziesz musiał sprecyzować dokładnie, co napisałeś i jak to nie działa.

Karl Knechtel
źródło
nie dostałem, dla pierwszego pytania nie zdefiniowałem mojej_listy. W moim programie jest to liczba losowa nie 1, 2, 3, 4 .. na drugie pytanie nie działa ze mną nie wiem dlaczego
layo
37
my_listjest definiowany tylko wtedy, gdy go zdefiniujesz. Miało to być miejsce dla dowolnej nazwy listy, z którą próbujesz pracować. Nie mogę zgadnąć, jak to nazwałeś.
Karl Knechtel,
2
6 lat później ten post wciąż pomaga ludziom. Miałem usterkę w kodzie i mogłem użyć twojego postu, aby potwierdzić, że pokrewne pojęcia w moim kodzie do twojego również były słuszne, więc problem musi leżeć gdzie indziej. Potem to znalazłem. Właśnie podziękowałem tobie i osobie z pytaniem o szybkim głosowaniu. Wszystkiego najlepszego.
TMWP
1
@KarlKnechtel Miał w swoim pytaniu listę, która nazywała się „ a”.
HelloGoodbye
1
Ponieważ zipzatrzymuje się, gdy osiągnie koniec krótszego argumentu, zip(my_list, my_list[1:])wystarczy.
chepner
114

Sumaryczna lista liczb:

sum(list_of_nums)

Obliczanie połowy n i n - 1 (jeśli mam prawidłowy wzorzec), przy użyciu rozumienia listy :

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

Suma sąsiednich elementów, np. ((1 + 2) / 2) + ((2 + 3) / 2) + ... używając redukcji i lambda

reduce(lambda x, y: (x + y) / 2, list_of_nums)
Rafe Kettler
źródło
4
Myślę, że chce zsumować sąsiednie elementy. Nie byłoby sensu biorąc średnią xi x - 1; zamiast tego moglibyśmy odjąć 0,5.
Karl Knechtel,
4
Funkcja zmniejszania nie robi tego, co mówi post. Oblicza (((a1 + a2) / 2 + a3) / 2 + a4) / 2 ...
Moberg
from functools import reduce
tyrex
70

Pytanie 2: Aby podsumować listę liczb całkowitych:

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

Jeśli lista zawiera liczby całkowite jako ciągi znaków:

a = ['5', '6']
# import Decimal: from decimal import Decimal
sum(Decimal(i) for i in a)
Evans Murithi
źródło
4
sum(i for i in a)jest po prostu zbędny.
Jean-François Fabre
6
sum(Decimal(i) for i in a)=> sum(int(i) for i in a)lubsum(map(int,a))
Jean-François Fabre
34

Możesz spróbować w ten sposób:

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
Md. Rezwanul Haque
źródło
4
nie ma potrzeby tworzenia takiej kopii, a jest to strasznie niepythonic. Unikaj zarazy pomimo wszystkich głosów ...
Jean-François Fabre
@ Jean-FrançoisFabre czy mógłbyś podać szczegóły swojego komentarza? Dlaczego jest to „okropnie niepythonic”?
PierreF
na początek a[0:len(a)]tworzy kopię a, po co marnować procesor i pamięć? potem print(sm)działa również w Pythonie 2. Nie rozumiem, dlaczego ma tak wiele pozytywnych opinii w połowie 2017 roku ... ale dotyczy to większości odpowiedzi tutaj.
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

Wygląda na to, że sumgdzieś został zdefiniowany w kodzie i zastępuje domyślną funkcję. Więc go usunąłem i problem został rozwiązany.

użytkownik4183543
źródło
16

Korzystanie z prostego list-comprehensioni sum:

>> sum(i for i in range(x))/2. #if x = 10 the result will be 22.5
AndreL
źródło
4
Nie musisz go używać [i ]możesz po prostu przekazać wyrażenie generatorasum(i/2. for i in range(x))
Ivan
1
sum(range(x)) / 2.unika wszystkich podziałów, po prostu dziel na końcu.
Jean-François Fabre
13

Wszystkie odpowiedzi wykazały podejście programowe i ogólne. Proponuję matematyczne podejście właściwe dla twojego przypadku. Może być szybszy, szczególnie w przypadku długich list. Działa, ponieważ twoja lista jest listą liczb naturalnych do n:

Załóżmy, że mamy liczby naturalne 1, 2, 3, ..., 10:

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

Możesz użyć sumfunkcji z listy:

>>> print sum(nat_seq)
55

Możesz także użyć formuły n*(n+1)/2gdzie njest wartością ostatniego elementu na liście (tutaj nat_seq[-1]:), aby uniknąć iteracji elementów:

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

Aby wygenerować sekwencję (1+2)/2, (2+3)/2, ..., (9+10)/2, możesz użyć generatora i formuły (2*k-1)/2.(zanotuj kropkę, aby wartości zmiennoprzecinkowe). Podczas generowania nowej listy musisz pominąć pierwszy element:

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

Tutaj także możesz użyć sumfunkcji z tej listy:

>>> print sum(new_seq)
49.5

Możesz jednak również użyć formuły (((n*2+1)/2)**2-1)/2, aby uniknąć iteracji elementów:

>>> print (((new_seq[-1]*2+1)/2)**2-1)/2
49.5
Ely
źródło
6

Najprostszy sposób rozwiązania tego problemu:

l =[1,2,3,4,5]
sum=0
for element in l:
    sum+=element
print sum
ShashankS
źródło
4

Odpowiedź na to pytanie znajduje się tutaj

a = [1,2,3,4] suma (a) zwraca 10

Vijay
źródło
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
źródło
3

Generatory to prosty sposób na napisanie tego:

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]
Jochen Ritzel
źródło
Możesz także podzielić przez 2,0, aby uniknąć podziału na liczby całkowite.
Chris Anderson
@ChrisAnderson nieprawda w Pythonie 3. Podział zmiennoprzecinkowy jest domyślny.
Justin Meiners,
3

Ułatwmy dla początkującego: -

  1. Słowo globalkluczowe pozwoli na przypisanie komunikatu zmiennej globalnej w ramach funkcji głównej bez tworzenia nowej zmiennej lokalnej
    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

Ta koncepcja nazywa się Shadowing

  1. Zsumuj listę liczb w Pythonie
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()

Wyjścia = 15

Aamir M. Meman
źródło
2

Korzystanie z pairwise przepisu 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) )
tzot
źródło
2

Krótkie i proste:

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

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

A oto jak to wygląda:

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

Ze względu na pewne głupoty w jaki Python obsługuje mapponad dwie listy, to trzeba obciąć listy a[:-1]. Działa więcej, niż można się spodziewać, jeśli używasz 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
źródło
Krótko tak. Prosty? Wymaga dłuższego wyjaśnienia niż długie rozwiązania, aby zrozumieć, co robi.
tekHedd
wprowadza to błąd kumulacji zmiennoprzecinkowej. Zamiast tego podziel się na końcu.
Jean-François Fabre
1
@ Jean-FrançoisFabre Obie metody są niedoskonałe - podział na końcu przepełni się w przypadku dużych liczb, rozwiązanie zależy od danych (i przypadku użycia).
cz
2

Tyle rozwiązań, ale wciąż brakuje mojego ulubionego:

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

tablica numpy nie różni się zbytnio od listy (w tym przypadku użycia), z tym wyjątkiem, że tablice można traktować jak liczby:

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

Gotowy!

wyjaśnienie

Fantazyjne wskaźniki oznaczają to: [1:]obejmują wszystkie elementy od 1 do końca (pomijając element 0) i [:-1]są wszystkimi elementami oprócz ostatniego:

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

Tak więc dodanie tych dwóch daje tablicę składającą się z elementów (1 + 2), (2 + 3) i tak dalej. Nie dlatego, że się dzielę 2.0, nie 2dlatego , że inaczej Python uważa, że ​​używasz tylko liczb całkowitych i generuje zaokrąglone wyniki liczb całkowitych.

zaletą korzystania z numpy

Numpy może być znacznie szybsze niż pętle wokół list numerów. W zależności od tego, jak duża jest twoja lista, kilka rzędów wielkości szybciej. Poza tym jest o wiele mniej kodu i przynajmniej dla mnie jest łatwiejszy do odczytania. Staram się nawiązywać nawyk korzystania z numpy dla wszystkich grup liczb i jest to ogromna poprawa dla wszystkich pętli i pętli wewnątrz pętli, które w innym przypadku musiałbym zrobić.

Zak
źródło
1

Po prostu użyłbym lambda z 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
źródło
1

Używam whilepętli, aby uzyskać wynik:

i = 0
while i < len(a)-1:
   result = (a[i]+a[i+1])/2
   print result
   i +=1
Aashutosh jha
źródło
1

Zapętlaj elementy na liście i aktualizuj sumę w następujący sposób:

def sum(a):
    total = 0
    index = 0
    while index < len(a):
        total = total + a[index]
        index = index + 1
    return total
Samueltommzy
źródło
1

Dzięki Karlowi Knechtelowi mogłem zrozumieć twoje pytanie. Moja interpretacja:

  1. Chcesz nową listę ze średnią elementu i i i + 1.
  2. Chcesz zsumować każdy element na liście.

Pierwsze pytanie za pomocą funkcji anonimowej (aka. Funkcja 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

Drugie pytanie również za pomocą funkcji anonimowej (aka. Funkcji Lambda):

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

Oba pytania połączone w jednym wierszu kodu:

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

użyj tego, który najlepiej odpowiada Twoim potrzebom

Stickysli
źródło
1

Możesz również zrobić to samo za pomocą rekurencji:

Fragment kodu w języku 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))
vijayraj34
źródło
0

Spróbuj użyć listy. Coś jak:

new_list = [(old_list[i] + old_list[i+1])/2 for i in range(len(old_list-1))]
TartanLama
źródło
@Rafe to działa (jeśli po prostu naprawimy nawiasy na końcu - powinno być range(len(old_list) - 1)), ale Pythoniści zazwyczaj marszczą brwi w kombinacji „zasięgu” i „len”. Następstwem tego „powinien być tylko jeden sposób” jest to, że „standardowa biblioteka umożliwia unikanie brzydkich rzeczy”. Pośrednia iteracja - iteracja po sekwencji liczb, abyś mógł użyć tych liczb do zindeksowania tego, co naprawdę chcesz iterować - jest brzydką rzeczą.
Karl Knechtel,
0

W duchu itertools. Inspiracja parą przepisu.

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

Przykłady:

>>>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
źródło
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)
vasanth kumar
źródło
0

Prostym sposobem jest użycie permutacji 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)

Wynik to:

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

Pamiętaj, że kolejność ma znaczenie - co oznacza, że ​​1, 2, 7 jest również pokazane jako 2, 1, 7 i 7, 1, 2. Możesz to zmniejszyć za pomocą zestawu.

Jesse
źródło
0

W Pythonie 3.8 można użyć nowego operatora przypisania

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

ajest bieżącym odwołaniem do poprzedniej wartości na liście, stąd jest inicjowana do pierwszego elementu listy, a iteracja następuje na pozostałej części listy, aktualizująca po użyciu w każdej iteracji.

Aby uniknąć konieczności tworzenia kopii listy, należy użyć jawnego iteratora my_list[1:].

chepner
źródło
-3

Spróbuj wykonać następujące czynności -

mylist = [1, 2, 3, 4]   

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

result = add(mylist)
print("sum = ", result)
Sai G.
źródło
2
Nowa odpowiedź powinna naprawdę wyraźnie różnić się od istniejących odpowiedzi. Ponadto twoja sumfunkcja nie różni się od wbudowanego sumzachowania lub nazwy. Możesz usunąć definicję funkcji z odpowiedzi i nadal będzie działać.
Noumenon,
czy możesz teraz sprawdzić
Sai G,
2
Doceniam to, że poprawiasz swoją odpowiedź! Nazwy zmiennych są bardziej opisowe i nie przesłaniają wbudowanych. Ale podstawowe problemy wciąż istnieją: podejście for-loop zostało już dostarczone przez stackoverflow.com/a/35359188/733092 powyżej, a funkcja jest redundantna z wbudowanym sum. Otrzymasz ocenę A w teście poprawnej odpowiedzi na pytanie, ale odpowiedzi StackOverflow również muszą być przydatne dla osób przybywających na tę stronę, a duplikaty odpowiedzi nie są.
Noumenon,