This question already has answers here:
How to find the cumulative sum of numbers in a list?
(25 answers)
Closed 8 years ago.
can you help me with code which returns partial sum of numbers in text file?
I must import text file, then make a code for partial sums without tools ..etc.
My input:
4
13
23
21
11
The output should be (without brackets or commas):
4
17
40
61
72
I was trying to make code in python, but could only do total sum and not partial one.
If i use the += operator for generator, it gives me an error!
Well, since everyone seems to be giving their favourite idiom for solving the problem, how about itertools.accumulate in Python 3:
>>> import itertools
>>> nums = [4, 13, 23, 21, 11]
>>> list(itertools.accumulate(nums))
[4, 17, 40, 61, 72]
There are a number of ways to create your sequence of partial sums. I think the most elegant is to use a generator.
def partial_sums(iterable):
total = 0
for i in iterable:
total += i
yield total
You can run it like this:
nums = [4, 13, 23, 21, 11]
sums = list(partial_sums(nums)) # [ 4, 17, 40, 61, 72]
Edit To read the data values from your file, you can use another generator, and chain them together. Here's how I'd do it:
with open("filename.in") as f_in:
# Sums generator that "feeds" from a generator expression that reads the file
sums = partial_sums(int(line) for line in f_in)
# Do output:
for value in sums:
print(value)
# If you need to write to a file, comment the loop above and uncomment this:
# with open("filename.out", "w") as f_out:
# f_out.writelines("%d\n" % value for value in sums)
numpy.cumsum will do what you want.
If you're not using numpy, you can write your own.
def cumsum(i):
s = 0
for elt in i:
s += elt
yield s
try this:
import numpy as np
input = [ 4, 13, 23, 21, 11 ]
output = []
output.append(input[0])
for i in np.arange(1,len(input)):
output.append(input[i] + input[i-1])
print output
Use cumulative sum in numpy:
import numpy as np
input = np.array([4, 13, 23, 21 ,11])
output = input.cumsum()
Result:
print output
>>>array([ 4, 17, 40, 61, 72])
Or if you need a list, you may convert output to list:
output = list(output)
print output
>>>[4, 17, 40, 61, 72]
This is an alternative solution using reduce:
nums = [4, 13, 23, 21, 11]
partial_sum = lambda a, b: a + [a[-1] + b]
sums = reduce(partial_sum, nums[1:], nums[0:1])
Pluses in lambda are not the same operator, the first one is list concatenation and the second one is sum of two integers. Altough Blckknght's may be more clear, this one is shorter and works in Python 2.7.
something like this:
>>> lst = [4, 13, 23, 21 ,11]
>>> [sum(lst[:i+1]) for i, x in enumerate(lst)]
[4, 17, 40, 61, 72]
Related
#!/usr/bin/python2
s=5 # input any int
l1=[5,8,2,1,17] # input some int numbers
l2=[] # will be out
for i in l1:
s+=i
l2.append(s)
print l1,l2
[5, 8, 2, 1, 17]
[10, 18, 20, 21, 38]
I would like to replace the above for cycle with listcomprehension.
I generally use list comprehensions but I don't know how could I do with the above for cycle.
For a list comprehension without using libraries or the overhead of sum(), you could use an internal list to store the accumulator.
l1 = [5,8,2,1,17]
s = 5
R = [a.append(a.pop(0)+n) or a[0] for a in [[s]] for n in l1]
print(R)
[10, 18, 20, 21, 38]
If you're using Python 3.8+ you can use the walrus operator to manage the accumulation:
R = [a := n + (a if i else s) for i,n in enumerate(l1)]
Here you can see use of sum(). However I would not prefer it if the list is too long for the repetitive calculations by sum()
>>> s=5
>>>
>>> l1=[5,8,2,1,17]
>>> [s+sum(l1[:i+1]) for i,x in enumerate(l1)]
[10, 18, 20, 21, 38]
>>>
List comprehensions are much better suited to situations where you generate an output item independently for each input item. Here, having to sum the items makes it rather inconvenient.
You could use itertools.accumulate, though, which is designed to do that by default:
from itertools import accumulate
l1 = [5, 8, 2, 1, 17]
s = 5
l2 = list(accumulate(l1, initial=s))[1:]
print(l2)
# [10, 18, 20, 21, 38]
(Note that we have to exclude the first value, which would be the initial s, as you don't want it in your output.)
You have the list-comprehension option
res = [s + sum(l1[:i+1]) for i,x in enumerate(l1)]
Or using some libs along with itertools.accumulate
from operator import add
from itertools import accumulate
import numpy as np
res = np.array(list(accumulate(l1, add))) + s
I need to write a program that reads a text file and returns the median of the numbers in the file. I think I have a good idea of how to approach this, but I got an AttributeError when running my program.
My question is: how do I make one list for the numbers in the text file? There are a total of 15 numbers, split across 5 lines in the file:
10 20 30
40 50 60
90 80 70
11 22 13
14 14 20
what I thought to do to create a list was:
num_list = fv.readlines()
num_list = num_list.split()
I thought this would read through all the lines of the file, then I could use the split function to create a list of the numbers. Now that I got an AttributeError: 'list' object has no attribute 'split', I'm unsure of what to do.
Without a solid expected result I assume you want all numbers in one list.
You can create an empty list then use list.extend as you loop through the file. You will need to cast them to int though. map is great for this:
num_list = []
with open('filename.txt') as fv:
for row in fv:
num_list.extend(map(int, row.split()))
More efficiently you can use re
import re
with open('filename.txt') as fv:
num_list = list(map(int, re.findall('\d+', fv.read())))
Result (for both above) will be:
[10, 20, 30, 40, 50, 60, 90, 80, 70, 11, 22, 13, 14, 14, 20]
Otherwise in sublists by line/row:
with open('filename.txt') as fv:
num_list = [list(map(int, row.split())) for row in fv]
Result for this:
[[10, 20, 30], [40, 50, 60], [90, 80, 70], [11, 22, 13], [14, 14, 20]]
I think that's what you want to do:
lines = fv.readlines()
num_list = []
for line in lines:
num_list.extend(line.split(' '))
num_list = [int(num.strip()) for num in num_list]
My answer is definitely a longer version but...
text = open('numbers.txt', 'r')
string = text.read()
string = string.replace('\n', ' ')
numbers = string.split(' ')
text.close()
#Print to see the result
print(numbers)
I have a large data of 145000 items (a bill of materials) and I want to check the % of shared items between two bill of materials.
Two for loops or other methods always run in similar time periods.
What is the fastest way to do this?
First&secondbill are the lists with components in them:
for FKid in FirstBill:
for SKid in SecondBill:
CommonChild = (CommonChild + 1) if FKid == SKid else CommonChild
return CommonChilds / len(FirstBill)
Kinda optimal to use one set
# Python program to illustrate the intersection
# of two lists in most simple way
def intersection(lst1, lst2):
temp = set(lst2)
lst3 = [value for value in lst1 if value in temp ]
return lst3
# Driver Code
lst1 = [4, 9, 1, 17, 11, 26, 28, 54, 69]
lst2 = [9, 9, 74, 21, 45, 11, 63, 28, 26]
#print(intersection(lst1, lst2))
quantity = len(intersection(lst1, lst2))
Assuming that ids in the bills are unique, a simpler answer would be:
percentage = sum([1 for fkid in FirstBill if fkid in SecondBill]) / len(FirstBill) * 100
or
percentage = len(set(FirstBill).intersection(set(SecondBill))) / len(FirstBill) * 100
I want to go through each element of an array I've created. However, I'm doing some debugging and it's not. Here's what I have so far and what it's printing out.
def prob_thirteen(self):
#create array of numbers 2-30
xcoords = [range(2,31)]
ycoords = []
for i in range(len(xcoords)):
print 'i:', xcoords[i]
output:
i: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
Why does 'i' return my whole array and not just the first element: 2? I'm not sure why this is returning my whole array.
xcoords = [range(2,31)]
This line will create an array of length 1. The only element in that array is an array of the numbers 2 -> 30. Your loop is printing the elements of the outer array. Change that line to:
xcoords = range(2,31)
This answer is correct for Python 2 because the range function returns a list. Python 3 will return a range object (which can be iterated on producing the required values). The following line should work in Python 2 and 3:
xoords = list(range(2,31))
First of all, change xcoords so that it isn't a list inside a list:
xcoords = range(2, 31)
We don't need to iterate over a list using an index into the list using len(xcoords). In python we can simply iterate over a list like this:
for coord in xcoords:
print "i: ", coord
If we did need to keep track of the index we could use enumerate:
for i, coord in enumerate(xcoords):
print str(i) + ":", coord
I have an array A
A = [5,2,8,14,6,13]
I want to get an array where each element is added to every other element, so the first five elements would be 5 + each element, then the next four would be 2 + each element etc.
So the result would be
B = [7,13,19,11,18, 10,16,8,15, 22,14,21, 20,27, 19]
What is the quickest way to do this without using for loops?
Note: The problem I am trying to solve involves large boolean arrays instead of integers and the actual operation is a boolean 'and', not merely addition. I have simplified the question for ease of explanation. I have been using for loops up to now, but I am looking for a faster alternative.
Use ` itertools.combinations
from itertools import combinations
a = [5,2,8,14,6,13]
print [sum(i) for i in list(combinations(a, 2))]
No need of list(). Thanks to #PeterWood
print [sum(i) for i in combinations(a, 2)]
Output:
[7, 13, 19, 11, 18, 10, 16, 8, 15, 22, 14, 21, 20, 27, 19]
Demo
You could do it recursively:
def add_value_to_rest(sequence):
if not sequence:
return []
else:
additional = sequence[0]
return ([additional + value for value in sequence] +
add_value_to_rest(sequence[1:]))
With generators, in Python 3:
def add_value_to_rest(sequence):
if sequence:
additional = sequence[0]
for value in sequence:
yield additional + value
yield from add_value_to_rest(sequence[1:])
Or with Python 2.7:
def add_value_to_rest(sequence):
if sequence:
additional = sequence[0]
for value in sequence:
yield additional + value
for value in add_value_to_rest(sequence[1:]):
yield value
A = [5,2,8,14,6,13]
B = []
for i, x in enumerate(A):
for l in range(len(A) - i - 1):
B.append(A[i] + A[i + l + 1])
print B
#[7, 13, 19, 11, 18, 10, 16, 8, 15, 22, 14, 21, 20, 27, 19]