I would like to write a piece of code which calculates the sum of the elements in each row of a list and returns a new list of the row sums. For example
def row_sums(square):
square = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 16]
]
print(row_sums(square))
This would give the output of [10, 26, 42, 58] As the sum of the first row equals 10, sum of the second row equals 26 and so on. However I would like to NOT use the built in sum function to do this. How would I go about doing this? Thanks in advance.
A simple piece of code for calculating the sum of the elements in each row of a list.
square = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 16]
]
su=[sum(i) for i in square]
print (su)
Output:
[10, 26, 42, 58]
If you really cant use the sum() function, here is a function to sum the rows, I've written it explicitly to show the steps but it would be worth looking at list comprehensions once you understand what is going on:
def row_sums(square):
# list to store sums
output = []
# go through each row in square
for row in square:
# variable to store row total
total = 0
# go through each item in row and add to total
for item in row:
total += item
# append the row's total to the output list
output.append(total)
# return the output list
return output
This can then be used as such:
square = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 16]
]
row_totals = row_sums(square)
EDIT:
In answer to your comment, I'd do something like this:
def sum_columns(square):
# as before have a list to store the totals
output = []
# assuming your square will have the same row length for each row
# get the number of columns
num_of_columns = len(square[0])
# iterate over the columns
for i in xrange(0, num_of_columns):
# store the total for the column (same as before)
total = 0
# for each row, get the value for the column and add to the column total
# (value at index i)
for row in square:
total += row[i]
# append the total to the output list
output.append(total)
# return the list of totals
return output
Write your own sum function...
The module functools has a useful reduce function that you can use to write your own sum function. If you are comfortable with lambda functions you could do it this way:
lst = [0,1,2,3,4,5]
which would give sum(lst) as 15. However your own sum function with reduce may look something like:
from functools import reduce
reduce(lambda x,y: x + y, l)
which woudld also give 15. You should be able to write the rest yourself (i.e it within another list working on rows).
You can also do it with comprehension and reduce:
[reduce(lambda x, y: x + y, item) for item in square]
You can add that lines to your existent function:
result = []
for row in square: # iterates trough a row
line = 0 #stores the total of a line
for num in row: #go trough every number in row
line += num #add that number to the total of that line
result.append(line) #append to a list the result
print(result) #finally return the total of every line sum's in a list
Well at a certain point you have to use the sum-function (either as sum() or "+") but you could use map like
list(map(sum, square))
Related
Consider a list of numbers from 0 to 50. I want to print all the combinations of elements from that list whose sum is equal to any given number say 41.
One combination is [4,5,7,9,16].I want to print other combinations like this.
You can use combinations(...) function from itertools
import itertools
nums = range(51)
for n in range(1, len(nums) + 1):
for p in itertools.combinations(nums, n):
if sum(p) == 41:
print(*p)
The following code is best used in a subroutine but it can be stand alone code.To change the average just change the number after the while loop. To change the amount of numbers change the amount of zeros in the lists. The random part can also be changed for the range of numbers.
def stats():
x =[0,0,0,0,0,0]
while mean(x) != 14.5:
x =[0,0,0,0,0,0]
for i in range(6):
a = random.randint(9,17)
x[i] = a
return x
The mean in this code is a separate subroutine that looks like this:
def mean(x):
y = sum(x)/6
return y
At the start of the code, you need to import the random library to allow the code to work properly. The only thing is that this code will only output one combination,such as:
stats()
[11, 12, 16, 17, 16, 15]
You could write a recursive generator to efficiently produce only the combinations of positive integers that sum up to the target number:
def sumSets(numbers,target):
if not target : yield []
if not numbers or target <= 0: return
yield from sumSets(numbers[1:],target)
yield from (numbers[:1]+ss for ss in sumSets(numbers[1:],target-numbers[0]))
nums = list(range(1,50,3))
for ss in sumSets(nums,41): print(ss)
[19, 22]
[16, 25]
[13, 28]
[10, 31]
[7, 34]
[4, 37]
[1, 40]
[1, 4, 7, 13, 16]
[1, 4, 7, 10, 19]
Note that, if you're looking for all combinations of numbers from 1 to 50 that sum up to 41, you're going to get a lot of them:
nums = list(range(1,51))
print(sum(1 for _ in sumSets(nums,41))) # 1260
Write a function, called filter_out(), which takes a list of integers as input and return the list filtered by only keeping numbers that are multiples of 5, or 7 but not both, e.g., list = [5, 7, 35, 49] returns [5, 7, 49].
My problem is I cannot remove the number which both are multiples of 5 and 7.
def filter_out(my_list):
a_list = []
for number in my_list:
if number % 5 == 0 or number % 7 == 0:
a_list.append(number)
return a_list
print(filter_out([1, 2, 3, 5]))
[5]
print(filter_out([5, 7, 35, 49]))
[5, 7, 49]
You can check if number can't be divided by 35.
if (number % 5 == 0 or number % 7 == 0) and number % 35 != 0:
a_list.append(number)
You have to add a condition that checks for that:
def filter_out(my_list):
a_list = []
for number in my_list:
if (number % 5 == 0 or number % 7 == 0) and number % 35 != 0:
a_list.append(number)
return a_list
I checked division by 35 because that is 5*7 of course
Solution
You could use the following function to vectorize the list using numpy and then
evaluate mod(list_array, 5) and mod(list_array, 7).
drop = find intersection of values in list_array that came out to be zero in previous step.
keep = all values - values from step-2 (this is what you want).
The final implementation is a single line function call as shown below.
# call function to get list of numbers to keep and to drop
keep, drop = process_to_keep(list_of_values, n=5, m=7)
Code with Example and Output
import numpy as np
# dummy data
l = [5, 7, 35, 49]
# function to process data
def process_to_keep(list_of_values, n=5, m=7):
a = np.array(list_of_values)
A = a%n
B = a%m
drop = set(a[A==0]).intersection(set(a[B==0]))
keep = set(a) - drop
return list(sorted(keep)), list(sorted(drop))
# call function to get list of numbers to keep and to drop
keep, drop = process_to_keep(l, n=5, m=7)
print(' keep: {}\n drop: {}'.format(keep, drop))
Output:
keep: [49, 5, 7]
drop: [35]
Another Example
The function is generic. And so we can test it against another list: [5,7,30,35,42,49,50,70,100,105].
keep, drop = process_to_keep([5,7,30,35,42,49,50,70,100,105], n=5, m=7)
print(' keep: {}\n drop: {}'.format(keep, drop))
Output:
keep: [5, 7, 30, 42, 49, 50, 100]
drop: [35, 70, 105]
One More Example
Assume you want to check if a list of numbers are individually divisible by 10 or 7, but not by both. The same function takes care of this as well.
keep, drop = process_to_keep([5,7,30,35,42,49,50,70,100,105], n=10, m=7)
print(' keep: {}\n drop: {}'.format(keep, drop))
Output:
keep: [5, 7, 30, 35, 42, 49, 50, 100, 105]
drop: [70]
I want to create a list that would be the difference between the last and the first element of each sublist of a list. Sublists are sublists of N elements, so I will have len(list)/K+1 elements in my final list.
Here is a little example:
I have a list : [0, 10, 20, 5, 10, 30, 20, 35]. I chose to have a maximum of 3 elements per sublist. I will have the following sublists [0, 10, 20], [5, 10, 30], [20, 35].
Now I apply the difference in each sublist and I get the values 20, 25, 15 (because 20-0, 30-5 and 35-20).
I want the result to be in a list, so to have [20, 25, 15] as a final result.
As requested in the original version of the question, and according to the edits made by the OP, we create a list of increasing sequences, then calculate the differences between the max and min of each of them:
def spans(data):
sequences = [[data[0]]]
for val in data[1:]:
if val >= sequences[-1][-1]:
sequences[-1].append(val)
else:
sequences.append([val])
return [s[-1] -s[0] for s in sequences]
Sample run with the OP's data:
data = [0, 10, 20, 5, 10, 30, 20, 35]
print(spans(data))
# [20, 25, 15]
Another one:
print(spans([2, 4, 6, 8, 9, 4, 5, -2, -1, 5, 4]))
# [7, 1, 7, 0]
Here is a script that should help you.
Care if you have only one element in the last sublist, I don't know how you want to deal with this case. I considered that the element is the result of this sublist, but maybe you want to ignore the last sublist or to have 0 as a result.
Explanations are the comments in the script:
# Initial list
l = [0, 10, 20, 5, 10, 30, 20, 35]
# Number of elements to consider in each sublist.
STEP = 3
# Get the size of the list
length = len(l)
# The result list, empty at the beginning, that will be populated by the differences
result_list = []
# Iterate through sublists of exactly STEP elements
i = 0
while (i+STEP-1)<length:
result_list.append(l[i+STEP-1]-l[i])
i += STEP
# Special case for the possible little last sublist
# No difference done and element is kept if there is only one element
if i==length-1:
result_list.append(l[-1])
# Else, do the difference in the last sublist
elif i<length-1:
result_list.append(l[-1]-l[i])
Here is the script that takes the max-min of each sublist, as OP asked primarily:
l = [1,2,3,4,5,6,7,8]
n = 3
def chunks(l, n):
"""Yield successive n-sized chunks from l."""
for i in range(0, len(l), n):
yield l[i:i + n]
# Create the sublists
grouped_l = list(chunks(l,n))
# Do the max-min on each sublists
res = []
for i in grouped_l:
res.append(max(i)-min(i))
If you could advice me how to write the script to split list by number of values I mean:
my_list =[11,11,11,11,12,12,15,15,15,15,15,15,20,20,20]
And there are 11-4,12-2,15-6,20-3 items.
So in next list for exsample range(0:100)
I have to split on 4,2,6,3 parts
So I counted same values and function for split list, but it doen't work with list:
div=Counter(my_list).values() ##counts same values in the list
def chunk(it, size):
it = iter(it)
return iter(lambda: tuple(islice(it, size)), ())
What do I need:
Out: ([0,1,2,3],[4,5],[6,7,8,9,10,11], etc...]
You can use enumerate, itertools.groupby, and operator.itemgetter:
In [45]: import itertools
In [46]: import operator
In [47]: [[e[0] for e in d[1]] for d in itertools.groupby(enumerate(my_list), key=operator.itemgetter(1))]
Out[47]: [[0, 1, 2, 3], [4, 5], [6, 7, 8, 9, 10, 11], [12, 13, 14]]
What this does is as follows:
First it enumerates the items.
It groups them, using the second item in each enumeration tuple (the original value).
In the resulting list per group, it uses the first item in each tuple (the enumeration)
Solution in Python 3 , If you are only using counter :
from collections import Counter
my_list =[11,11,11,11,12,12,15,15,15,15,15,15,20,20,20]
count = Counter(my_list)
div= list(count.keys()) # take only keys
div.sort()
l = []
num = 0
for i in div:
t = []
for j in range(count[i]): # loop number of times it occurs in the list
t.append(num)
num+=1
l.append(t)
print(l)
Output:
[[0, 1, 2, 3], [4, 5], [6, 7, 8, 9, 10, 11], [12, 13, 14]]
Alternate Solution using set:
my_list =[11,11,11,11,12,12,15,15,15,15,15,15,20,20,20]
val = set(my_list) # filter only unique elements
ans = []
num = 0
for i in val:
temp = []
for j in range(my_list.count(i)): # loop till number of occurrence of each unique element
temp.append(num)
num+=1
ans.append(temp)
print(ans)
EDIT:
As per required changes made to get desired output as mention in comments by #Protoss Reed
my_list =[11,11,11,11,12,12,15,15,15,15,15,15,20,20,20]
val = list(set(my_list)) # filter only unique elements
val.sort() # because set is not sorted by default
ans = []
index = 0
l2 = [54,21,12,45,78,41,235,7,10,4,1,1,897,5,79]
for i in val:
temp = []
for j in range(my_list.count(i)): # loop till number of occurrence of each unique element
temp.append(l2[index])
index+=1
ans.append(temp)
print(ans)
Output:
[[54, 21, 12, 45], [78, 41], [235, 7, 10, 4, 1, 1], [897, 5, 79]]
Here I have to convert set into list because set is not sorted and I think remaining is self explanatory.
Another Solution if input is not always Sorted (using OrderedDict):
from collections import OrderedDict
v = OrderedDict({})
my_list=[12,12,11,11,11,11,20,20,20,15,15,15,15,15,15]
l2 = [54,21,12,45,78,41,235,7,10,4,1,1,897,5,79]
for i in my_list: # maintain count in dict
if i in v:
v[i]+=1
else:
v[i]=1
ans =[]
index = 0
for key,values in v.items():
temp = []
for j in range(values):
temp.append(l2[index])
index+=1
ans.append(temp)
print(ans)
Output:
[[54, 21], [12, 45, 78, 41], [235, 7, 10], [4, 1, 1, 897, 5, 79]]
Here I use OrderedDict to maintain order of input sequence which is random(unpredictable) in case of set.
Although I prefer #Ami Tavory's solution which is more pythonic.
[Extra work: If anybody can convert this solution into list comprehension it will be awesome because i tried but can not convert it to list comprehension and if you succeed please post it in comments it will help me to understand]
I am trying to do the following..
I have a list of n elements. I want to split this list into 32 separate lists which contain more and more elements as we go towards the end of the original list. For example from:
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
I want to get something like this:
b = [[1],[2,3],[4,5,6,7],[8,9,10,11,12]]
I've done the following for a list containing 1024 elements:
for i in range (0, 32):
c = a[i**2:(i+1)**2]
b.append(c)
But I am stupidly struggling to find a reliable way to do it for other numbers like 256, 512, 2048 or for another number of lists instead of 32.
Use an iterator, a for loop with enumerate and itertools.islice:
import itertools
def logsplit(lst):
iterator = iter(lst)
for n, e in enumerate(iterator):
yield itertools.chain([e], itertools.islice(iterator, n))
Works with any number of elements. Example:
for r in logsplit(range(50)):
print(list(r))
Output:
[0]
[1, 2]
[3, 4, 5]
[6, 7, 8, 9]
... some more ...
[36, 37, 38, 39, 40, 41, 42, 43, 44]
[45, 46, 47, 48, 49]
In fact, this is very similar to this problem, except it's using enumerate to get variable chunk sizes.
This is incredibly messy, but gets the job done. Note that you're going to get some empty bins at the beginning if you're logarithmically slicing the list. Your examples give arithmetic index sequences.
from math import log, exp
def split_list(_list, divs):
n = float(len(_list))
log_n = log(n)
indices = [0] + [int(exp(log_n*i/divs)) for i in range(divs)]
unfiltered = [_list[indices[i]:indices[i+1]] for i in range(divs)] + [_list[indices[i+1]:]]
filtered = [sublist for sublist in unfiltered if sublist]
return [[] for _ in range(divs- len(filtered))] + filtered
print split_list(range(1024), 32)
Edit: After looking at the comments, here's an example that may fit what you want:
def split_list(_list):
copy, output = _list[:], []
length = 1
while copy:
output.append([])
for _ in range(length):
if len(copy) > 0:
output[-1].append(copy.pop(0))
length *= 2
return output
print split_list(range(15))
# [[0], [1, 2], [3, 4, 5, 6], [7, 8, 9, 10, 11, 12, 13, 14]]
Note that this code is not efficient, but it can be used as a template for writing a better algorithm.
Something like this should solve the problem.
for i in range (0, int(np.sqrt(2*len(a)))):
c = a[i**2:min( (i+1)**2, len(a) )]
b.append(c)
Not very pythonic but does what you want.
def splitList(a, n, inc):
"""
a list to split
n number of sublist
inc ideal difference between the number of elements in two successive sublists
"""
zr = len(a) # remaining number of elements to split into sublists
st = 0 # starting index in the full list of the next sublist
nr = n # remaining number of sublist to construct
nc = 1 # number of elements in the next sublist
#
b=[]
while (zr/nr >= nc and nr>1):
b.append( a[st:st+nc] )
st, zr, nr, nc = st+nc, zr-nc, nr-1, nc+inc
#
nc = int(zr/nr)
for i in range(nr-1):
b.append( a[st:st+nc] )
st = st+nc
#
b.append( a[st:max(st+nc,len(a))] )
return b
# Example of call
# b = splitList(a, 32, 2)
# to split a into 32 sublist, where each list ideally has 2 more element
# than the previous
There's always this.
>>> def log_list(l):
if len(l) == 0:
return [] #If the list is empty, return an empty list
new_l = [] #Initialise new list
new_l.append([l[0]]) #Add first iteration to new list inside of an array
for i in l[1:]: #For each other iteration,
if len(new_l) == len(new_l[-1]):
new_l.append([i]) #Create new array if previous is full
else:
new_l[-1].append(i) #If previous not full, add to it
return new_l
>>> log_list([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
[[1], [2, 3], [4, 5, 6], [7, 8, 9, 10]]