Tổng hợp danh sách các số trong Python


367

Tôi có một danh sách các số như [1,2,3,4,5...], và tôi muốn tính toán (1+2)/2và cho lần thứ hai, (2+3)/2và thứ ba, (3+4)/2v.v. Làm thế nào tôi có thể làm điều đó?

Tôi muốn tính tổng số thứ nhất với số thứ hai và chia cho 2, sau đó tổng số thứ hai với số thứ ba và chia cho 2, v.v.

Ngoài ra, làm thế nào tôi có thể tổng hợp một danh sách các số?

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

Là nó:

b = sum(a)
print b

để có được một số?

Điều này không làm việc cho tôi.


Danh sách này dài bao nhiêu? làm thế nào ngẫu nhiên là các giá trị, giữa 0 và 1?
kevpie

2
nếu bạn xác định sum trước khi nó có thể gây rối python, hãy thử del sum. có lẽ nó đã được định nghĩa trong mã ở đâu đó và ghi đè hàm mặc định. Vì vậy, tôi đã xóa nó và vấn đề đã được giải quyết. (câu trả lời của người dùng4183543)
NicoKowe

1
"Điều này không hoạt động" không phải là một mô tả vấn đề.
Hầu tước Lorne

Câu trả lời:


279

Câu 1: Vì vậy, bạn muốn (phần tử 0 + phần tử 1) / 2, (phần tử 1 + phần tử 2) / 2, ... vv

Chúng tôi lập hai danh sách: một trong mọi yếu tố ngoại trừ đầu tiên và một trong mọi yếu tố ngoại trừ cuối cùng. Sau đó, trung bình chúng tôi muốn là trung bình của mỗi cặp được lấy từ hai danh sách. Chúng tôi sử dụng zipđể lấy cặp từ hai danh sách.

Tôi giả sử bạn muốn xem số thập phân trong kết quả, mặc dù giá trị đầu vào của bạn là số nguyên. Theo mặc định, Python thực hiện phân chia số nguyên: nó loại bỏ phần còn lại. Để phân chia mọi thứ theo mọi cách, chúng ta cần sử dụng các số dấu phẩy động. May mắn thay, chia một int cho một float sẽ tạo ra một float, vì vậy chúng ta chỉ sử dụng 2.0cho ước số của chúng ta thay vì 2.

Như vậy:

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

Câu hỏi 2:

Mà sử dụng sumnên hoạt động tốt. Các công việc sau đây:

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

Ngoài ra, bạn không cần chỉ định mọi thứ cho một biến ở mỗi bước trên đường đi. print sum(a)hoạt động tốt

Bạn sẽ phải cụ thể hơn về chính xác những gì bạn đã viết và cách nó không hoạt động.


Tôi đã không nhận được, vì câu hỏi đầu tiên tôi đã xác định my_list không xác định. Trong chương trình của tôi, một số ngẫu nhiên không phải 1, 2, 3, 4 .. cho câu hỏi thứ hai tôi không làm việc với tôi, tôi không biết tại sao
layo

37
my_listchỉ được xác định nếu bạn xác định nó. Đó được cho là một người giữ chỗ cho bất cứ điều gì bạn gọi là danh sách mà bạn đang cố gắng làm việc. Tôi không thể đoán những gì bạn gọi nó.
Karl Knechtel

2
6 năm sau, bài này vẫn đang giúp mọi người. Tôi đã có một trục trặc trong mã của mình và đã có thể sử dụng bài đăng của bạn để xác nhận rằng các khái niệm liên quan trong mã của tôi với bạn cũng đúng, vì vậy vấn đề phải nằm ở chỗ khác. Sau đó tôi tìm thấy nó. Chỉ cần cho bạn và người có câu hỏi bỏ phiếu là một lời cảm ơn nhanh chóng. Lời chúc tốt nhất.
TMWP 17/03/2017

1
@KarlKnechtel Anh ấy có một danh sách trong câu hỏi của anh ấy và nó được gọi là " a".
HelloGoodbye

1
zipdừng lại một khi nó đạt đến cuối của đối số ngắn hơn, zip(my_list, my_list[1:])là đủ.
chepner

115

Danh sách tổng hợp các số:

sum(list_of_nums)

Tính một nửa của n và n - 1 (nếu tôi có mẫu đúng), sử dụng cách hiểu danh sách :

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

Tổng các phần tử liền kề, ví dụ ((1 + 2) / 2) + ((2 + 3) / 2) + ... bằng cách sử dụng giảmlambdas

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

4
Tôi nghĩ rằng anh ấy muốn tổng hợp các yếu tố liền kề. Sẽ không có điểm nào trong việc lấy trung bình xx - 1; thay vào đó chúng ta chỉ có thể trừ 0,5.
Karl Knechtel

4
Hàm giảm không làm những gì bài viết nói. Nó tính toán (((a1 + a2) / 2 + a3) / 2 + a4) / 2 ...
Moberg

from functools import reduce
tyrex

70

Câu 2: Để tổng hợp danh sách các số nguyên:

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

Nếu danh sách chứa số nguyên dưới dạng chuỗi:

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

4
sum(i for i in a)chỉ là dư thừa.
Jean-François Fabre

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

34

Bạn có thể thử theo cách này:

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
không cần phải tạo một bản sao như thế này, và nó thật kinh khủng. Tránh như bệnh dịch bất chấp tất cả các phiếu bầu ...
Jean-François Fabre

@ Jean-FrançoisFabre bạn có thể vui lòng nêu chi tiết bình luận của bạn? Tại sao điều này là "unpythonic khủng khiếp"?
PierreF

để bắt đầu a[0:len(a)]tạo một bản sao a, điểm gì ngoài việc lãng phí CPU & bộ nhớ? sau đó print(sm)cũng hoạt động trong python 2. Tôi không hiểu tại sao điều này có quá nhiều sự ủng hộ vào giữa năm 2017 ... nhưng nó áp dụng cho hầu hết các câu trả lời ở đây.
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

Có vẻ như sumđã được xác định trong mã ở đâu đó và ghi đè hàm mặc định. Vì vậy, tôi đã xóa nó và vấn đề đã được giải quyết.


16

Sử dụng đơn giản list-comprehensionsum:

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

4
Bạn không cần sử dụng [], bạn chỉ có thể chuyển biểu thức trình tạosum(i/2. for i in range(x))
Ivan

1
sum(range(x)) / 2.tránh tất cả các bộ phận, chỉ cần phân chia cuối cùng.
Jean-François Fabre

13

Tất cả các câu trả lời đã cho thấy một cách tiếp cận có lập trình và chung. Tôi đề nghị một phương pháp toán học cụ thể cho trường hợp của bạn. Nó có thể nhanh hơn đặc biệt cho các danh sách dài. Nó hoạt động vì danh sách của bạn là một danh sách các số tự nhiên lên đến n:

Giả sử chúng ta có các số tự nhiên 1, 2, 3, ..., 10:

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

Bạn có thể sử dụng sumchức năng trong danh sách:

>>> print sum(nat_seq)
55

Bạn cũng có thể sử dụng công thức n*(n+1)/2trong đó ngiá trị của phần tử cuối cùng trong danh sách (ở đây nat_seq[-1]:), vì vậy bạn tránh lặp lại các phần tử:

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

Để tạo chuỗi, (1+2)/2, (2+3)/2, ..., (9+10)/2bạn có thể sử dụng trình tạo và công thức (2*k-1)/2.(lưu ý dấu chấm để tạo các giá trị dấu phẩy động). Bạn phải bỏ qua phần tử đầu tiên khi tạo danh sách mới:

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

Ở đây cũng vậy, bạn có thể sử dụng sumchức năng trong danh sách đó:

>>> print sum(new_seq)
49.5

Nhưng bạn cũng có thể sử dụng công thức (((n*2+1)/2)**2-1)/2, vì vậy bạn có thể tránh lặp lại các phần tử:

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

6

Cách đơn giản nhất để giải quyết vấn đề này:

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

Máy phát điện là một cách dễ dàng để viết này:

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]

Bạn cũng có thể chia cho 2.0 để tránh chia số nguyên.
Chris Anderson

@ChrisAnderson không đúng trong python 3. phép chia dấu phẩy động là mặc định.
Justin Meiners

3

Hãy để chúng tôi làm cho nó dễ dàng cho người mới bắt đầu: -

  1. Các globaltừ khóa sẽ cho phép nhắn biến toàn cầu được giao trong phạm vi chức năng chính mà không tạo ra một biến địa phương mới
    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

Khái niệm này được gọi là Shadowing

  1. Tổng hợp danh sách các số trong 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()

Đầu ra = 15


2

Sử dụng pairwise công thức 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

Ngắn gọn và đơn giản:

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

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

Và đây là giao diện của nó:

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

Do một số sự ngu ngốc trong cách Python xử lý maphơn hai danh sách, bạn phải cắt bớt danh sách , a[:-1]. Nó hoạt động nhiều hơn bạn mong đợi nếu bạn sử dụng 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]

Ngắn, vâng. Đơn giản? Nó đòi hỏi một lời giải thích dài hơn các giải pháp dài để hiểu những gì nó đang làm.
tekHedd

điều này giới thiệu lỗi tích lũy điểm nổi. Thay vào đó hãy chia cuối cùng.
Jean-François Fabre

1
@ Jean-FrançoisFabre Cả hai phương pháp đều không hoàn hảo - phân chia ở cuối sẽ tràn cho số lượng lớn, giải pháp phụ thuộc vào dữ liệu (và trường hợp sử dụng).
cz

2

Rất nhiều giải pháp, nhưng yêu thích của tôi vẫn còn thiếu:

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

một mảng numpy không quá khác biệt với một danh sách (trong trường hợp sử dụng này), ngoại trừ việc bạn có thể coi các mảng như số:

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

Làm xong!

giải trình

Các chỉ số ưa thích có nghĩa là: [1:]bao gồm tất cả các phần tử từ 1 đến cuối (do đó bỏ qua phần tử 0) và [:-1]là tất cả các phần tử ngoại trừ phần tử cuối cùng:

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

Vì vậy, việc thêm hai cái đó cung cấp cho bạn một mảng bao gồm elemens (1 + 2), (2 + 3), v.v. Không phải tôi đang chia cho 2.0, không phải 2vì Python khác tin rằng bạn chỉ sử dụng số nguyên và tạo ra kết quả số nguyên tròn.

lợi thế của việc sử dụng numpy

NumPy có thể nhiều nhanh hơn so với vòng xung quanh danh sách các số. Tùy thuộc vào mức độ lớn của danh sách của bạn, một số đơn đặt hàng có cường độ nhanh hơn. Ngoài ra, nó ít mã hơn rất nhiều, và ít nhất với tôi, nó dễ đọc hơn. Tôi đang cố gắng tạo thói quen sử dụng numpy cho tất cả các nhóm số và đó là một cải tiến lớn đối với tất cả các vòng lặp và vòng lặp trong vòng mà tôi sẽ phải thực hiện.


1

Tôi chỉ sử dụng lambda với 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

Tôi sử dụng một whilevòng lặp để có được kết quả:

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

1

Lặp lại các yếu tố trong danh sách và cập nhật tổng số như thế này:

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

1

Nhờ Karl Knechtel tôi đã có thể hiểu câu hỏi của bạn. Lời giải thích của tôi:

  1. Bạn muốn có một danh sách mới với mức trung bình của phần tử i và i + 1.
  2. Bạn muốn tổng hợp từng yếu tố trong danh sách.

Câu hỏi đầu tiên sử dụng chức năng ẩn danh (còn gọi là chức năng 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

Câu hỏi thứ hai cũng sử dụng chức năng ẩn danh (còn gọi là chức năng Lambda):

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

Cả hai câu hỏi kết hợp trong một dòng mã:

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

sử dụng một trong những phù hợp nhất với nhu cầu của bạn


1

Bạn cũng có thể làm tương tự bằng cách sử dụng đệ quy:

Đoạn mã 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

Hãy thử sử dụng một danh sách hiểu. Cái gì đó như:

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

@Rafe là một công việc hiệu quả (nếu chúng ta chỉ sửa các dấu ngoặc đơn ở cuối - nên range(len(old_list) - 1)), nhưng Pythonistas thường cau mày khi kết hợp 'phạm vi' và 'len'. Một hệ quả của "chỉ nên có một cách để làm điều đó" là "thư viện tiêu chuẩn cung cấp một cách để bạn tránh những điều xấu xí". Lặp lại gián tiếp - lặp qua một chuỗi các số, để bạn có thể sử dụng các số đó để lập chỉ mục những gì bạn thực sự muốn lặp lại - là một điều xấu xí.
Karl Knechtel

0

Trong tinh thần của itertools. Cảm hứng từ công thức cặp.

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

Ví dụ:

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

Một cách đơn giản là sử dụng hoán vị 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)

Kết quả là:

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

Lưu ý rằng các vấn đề về thứ tự - có nghĩa là 1, 2, 7 cũng được hiển thị là 2, 1, 7 và 7, 1, 2. Bạn có thể giảm điều này bằng cách sử dụng một bộ.


0

Trong Python 3.8, toán tử gán mới có thể được sử dụng

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

alà một tham chiếu đang chạy đến giá trị trước đó trong danh sách, do đó nó được khởi tạo thành phần tử đầu tiên của danh sách và việc lặp lại xảy ra so với phần còn lại của danh sách, cập nhật asau khi được sử dụng trong mỗi lần lặp.

Một trình vòng lặp rõ ràng được sử dụng để tránh cần phải tạo một bản sao của danh sách bằng cách sử dụng my_list[1:].


-3

Hãy thử như sau -

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
Một câu trả lời mới nên thực sự khác biệt với các câu trả lời hiện có. Ngoài ra, sumchức năng của bạn không khác với sumhành vi hoặc tên tích hợp. Bạn thực sự có thể xóa định nghĩa hàm khỏi câu trả lời của bạn và nó vẫn hoạt động.
Noumenon

bạn có thể vui lòng kiểm tra ngay bây giờ
Sai G

2
Tôi đánh giá cao rằng bạn đang cải thiện câu trả lời của bạn! Các tên biến được mô tả nhiều hơn và không phủ bóng các phần dựng sẵn. Nhưng các vấn đề cơ bản vẫn còn đó: cách tiếp cận vòng lặp đã được cung cấp bởi stackoverflow.com/a353359188/733092 ở trên và chức năng này là dự phòng với tích hợp sẵn sum. Bạn sẽ đạt điểm A trong bài kiểm tra để trả lời chính xác câu hỏi, nhưng câu trả lời của StackOverflow cũng cần phải hữu ích cho những người đến trang này và các câu trả lời trùng lặp không có.
Noumenon
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.