How to iterate through a list and sum members together - python

Using Python 3.3, I have a list as such:
>>> ls
[250313, 242517, 243788, 1606025, 1566365, 1573483]
I need a for loop or built-in function to iterate over this, summing three integers together at a time.
I would like the end result to look like this:
>>> newls
[736618, 4745873]
It seems like itertools or sum would be helpful for this, but I can't seem to figure it out yet.

Take the sum of each consecutive three-element sublist of ls as so:
newls = [sum(ls[i:i+3]) for i in range(0, len(ls), 3)]
Note that, if len(ls) is not a multiple of three, the last one or two elements of ls will be summed together to make the last element of newls. To ignore any trailing elements that aren't part of a group of three, do:
newls = [sum(ls[i:i+3]) for i in range(0, len(ls) - len(ls) % 3, 3)]

Reshape your array into a matrix of dimensionality len(ls)/3 by 3, and then sum elements in each row.
import numpy as np
result = np.array(ls).reshape((-1,3)).sum(axis = 1)

Related

make pairwise difference of array with python

I have an array with numbers like this, in this case 5 numbers:
a = array([2.88581812, 2.8930633 , 2.85603976, 2.86739916, 2.85736707])
I would like to create an array of 10 elements in which the pairwise difference of all the numbers of the array is present.
For now i used nested loop for like this:
diffmean = []
for i in range(len(a)-1):
for j in range(i+1, len(a)):
diffmean.append(a[i]-a[j])
Obtaining a list with 10 elements of pairwise difference
[-0.007245185215707384,
0.029778354907735505,
0.018418952746142025,
0.0284510446999775,
0.03702354012344289,
0.02566413796184941,
0.035696229915684885,
-0.01135940216159348,
-0.0013273102077580035,
0.010032091953835476]
there is a "pythonic" way to perform this? without loopfor or nested loop for?
You can use combinations in build-in itertools library. Like:
from itertools import combinations
a = [2.88581812, 2.8930633 , 2.85603976, 2.86739916, 2.85736707]
diffmean = []
for b,c in combinations(a, 2):
diffmean.append(b - c)
The second argument of the function is the number of elements you want to combine. The function is order-free and the order-based version is permutations which returns 20 values in this case.
Assuming a is is numpy array. The below should work, but perhaps a more efficient solution exists as this calculates differences twices
np.expand_dims(a, 1) - a
d[np.tril_indices(a.size, k=-1)]

All possible combination of lists for a given list

I would like to have all possible combinations of lists of a given size.
Lets say for example, I have a given list K, such as K = [3, 5, 2]. With the following code I get what I desire. But how do I generalize this for any list of a given size, without just adding for loops?
assignment= []
for l in range(K[0]):
for m in range(K[1]):
for n in range(K[2]):
a = [l,m,n]
assignment.append(a)
The itertools library can often help with things like this. itertools.product() in particular, using * to pass it a list or iterator of ranges:
list(itertools.product(*(range(n) for n in K))
or
list(itertools.product(*map(range, K)))

Repeat values in a column based on another

Suppose I have an array (not necessarily square)
my_array = ['name_1', 3
'name_2', 2]
and I want to end up with an list (or numpy array etc) of length 3+2=5 where the first three positions are assigned to 'name_1' and the next 2 to 'name_2'. Hence the output will be
['name_1', 'name_1', 'name_1', 'name_2', 'name_2']
This is what I have done so far; Is there a better way to do this please?
import numpy as np
my_array = np.array([['name_1', 3], ['name_2', 2]])
l = []
for i in range(my_array.shape[0]):
x = [my_array[i, 0].tolist()] * np.int(my_array[i, 1])
l.append(x)
flat_list = [item for sublist in l for item in sublist]
print(flat_list)
which prints:
['name_1', 'name_1', 'name_1', 'name_2', 'name_2']
Thanks!
Use np.repeat:
my_array[:,0].repeat(my_array[:,1].astype(int))
# array(['name_1', 'name_1', 'name_1', 'name_2', 'name_2'], dtype='<U6')
You can use a combination of list multiplication and sum:
sum(([my_array[i]] * my_array[i+1] for i in range(0, len(my_array), 2)), [])
I'm not a numpy expert, and "better" way is subjective. Here's one way using itertools
from itertools import chain, repeat
chain.from_iterable(repeat(elem, count) for elem, count in zip(my_array[::2], my_array[1::2]))
Here's a breakdown of how it works.
my_array[::2] returns a slice that is every other element, since the first and and second arguments are left empty, it starts at 0 and goes to the end. So that will be all of your first column, which are your input elements. Your counts are in the other column, so we can use my_array[1::2] to get the counts. These slices are nice, because they don't create new copies of your array, just "views" that skip every other element and start at some offset.
Now we want to enumerate those in pairs. Using zip() is handy for that. It consumes iterators/generators/sequences in parallel and gives an individual binding for each element. So as we zip through in the for construct, we bind each element to elem, and each count to count.
The for in construct allows us to provide a transform for each pair of arguments. Here we use repeat to build up virtual repetitions of each element. A nice thing again, is that we don't actually have to create new arrays. The repeat generator will just produce the input element N times.
Finally, we want a way to string all of this repeated elements into one flattened enumeration. That's where chain.from_iterable() comes in. It consumes an iterable of iterables, unrolling each one in series. Like the other pieces, chain will produce a new generator, not a new list, so we again save on memory. If you indeed want a list, you can feed it to list() at the end. Or just make it the input to a for in construct.
Here's all of that broken out into individual operations with intention-revealing-variables:
elements = my_array[::2]
counts = my_array[1::2]
bypairs = zip(elements, counts)
repeated = (repeat(elem, count) for elem, count in bypairs)
flattened = chain.from_iterable(repeated)
list(flattened)
Here's another approach, skipping itertools, favoring generators:
def expanded(matrix):
stream = iter(matrix)
for element, count in zip(stream, stream):
for _ in range(count):
yield element
list(expanded(my_array))
Using list comprehension:
In [3]: my_array = ['name_1', 3, 'name_2', 2]
In [4]: out = [i for i, j in zip(my_array[::2], my_array[1::2]) for _ in range(j)]
In [5]: out
Out[5]: ['name_1', 'name_1', 'name_1', 'name_2', 'name_2']

Converting combinations of integers into list of sums of these combinations

I need to do this: I have list of integers, i make all possible combinations containing 3 of these numbers, and output is list containing sums of these combinations. (not sum of all combinations together, but for each combination one sum)
My algorithm do it in this way: make list of all possible combinations, then count sum of each combination and save it into list, what is too uneffective if number of integers is large. Here is little sample in python:
import itertools
array=[1,2,3,4]
combs=[]
els = [list(x) for x in itertools.combinations(array, 3)]
combs.extend(els)
result=list(map(sum, combs))
Could you please come up with some more effective solution? Maybe if there is some way of making it a loop where there isn't made a list of combinations at first and counted sum of each combination at second but rather it straight counts sum of just created combination, saves it into list and then continues to another one until all combinations and sums are done.
sum() works with any iterable, not just lists. You could make the code more efficient by applying it directly to the combinations' tuples:
result = [sum(c) for c in itertools.combinations(array, 3)]
If you want to process the result lazily, you can use a generator expression as well:
result = (sum(c) for c in itertools.combinations(array, 3))

How to Create Combination of Element in Different Set?

Let say that I have n lists and they are not disjoint. I want to make every combination of n elements which I get one from every lists I have but in that combination there are different elements and there are no double combination. So, [1,1,2] isn't allowed and [1,2,3] is same as [2,1,3].
For example, I have A=[1,2,3], B=[2,4,1], and C=[1,5,3]. So, the output that I want is [[1,2,5],[1,2,3],[1,4,5],[1,4,3],[2,4,1],[2,4,5],[2,4,3],[3,2,5],[3,4,5],[3,1,5]].
I have search google and I think function product in module itertools can do it. But, I have no idea how to make no same elements in every combinations and no double combinations.
Maybe something like:
from itertools import product
A=[1,2,3]
B=[2,4,1]
C=[1,5,3]
L = list(set([ tuple(sorted(l)) for l in product(A,B,C) if len(set(l))==3 ]))
Of course you would have to change 3 ot the relevant value if you work with more than 3 lists.
how about this? create a dicitonary with the sorted permutations as key. accept values only if all the three integers are different:
from itertools import product
A=[1,2,3]
B=[2,4,1]
C=[1,5,3]
LEN = 3
dct = {tuple(sorted(item)): item for item in product(A,B,C)
if len(set(item)) == LEN}
print(dct)
vals = list(dct.values())
print(vals)

Categories