Python range with fixed number of elements and fixed interval - python

I need to create a range like this in Pyhton:
1 ... 4 ... 7 ... 10 ... 13 ... 16 ...
But I would like to estabilish not the end of range, but the number of elements.
For example:
range_num_of_elements(1, num_of_elements=4, interval=3)
Gives as result:
[1, 4, 7, 10]
How can I do it?
EDIT: this question
Creating a range with fixed number of elements (length)
Doesn't answers my question. I wanna specify start, interval, num, where the question above specifies start, end, num.

you could define your range just like this:
def my_range(start, num_elements, step):
return range(start, start+step*num_elements, step)
list(my_range(1, 4, 3))
# [1, 4, 7, 10]
this would have all the nice features of range; e.g.:
7 in my_range(1, 4, 3) # True
8 in my_range(1, 4, 3) # False

You can use a list comprehension:
[start + interval * n for n in range(num_of_elements)]
Where
start = 1
interval = 3
num_of_elements = 4
This will give
[1, 4, 7, 10]
Or you can just compute the appropriate arguments to range, as Tom Karzes suggested in the comments:
range(start, start + interval * num_of_elements, interval)

Related

Array rotation(Juggling method) in python - List Index out of range

Array rotation can be done by slicing in python or even some other easier way too. But, I found a method in GFG - which has the following procedure to rotate an array:
Instead of moving one by one, divide the array into different sets where a number of sets are equal to GCD of n and d and move the elements within sets.
If GCD is 1, then, for example, array (n = 7 and d =2), then elements will be moved within one set only, we just start with temp = arr[0] and keep moving arr[I+d] to arr[I] and finally store temp at the right place.
Here is an example for n =12 and d = 3. GCD is 3 and
Let arr[] be {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}
a) Elements are first moved in first set –
arr[] after this step --> {4 2 3 7 5 6 10 8 9 1 11 12}
b)Then in second set.
arr[] after this step --> {4 5 3 7 8 6 10 11 9 1 2 12}
c)Finally in the third set.
arr[] after this step --> {4 5 6 7 8 9 10 11 12 1 2 3}
I tried to implement this method in python:
arr = [9,8,0,3,4,5,6,7,8]
d=3
for i in range(d):
for j in range(i,len(arr),d):
if j+1 == len(arr)-d+(i+1):
break
temp = arr[j]
arr[j]=arr[j+d]
arr[j+d] = temp
print(arr)
I don't know where I have gone wrong with the code. For this particular array as well as d value(rotation value) - I get the perfect output : [3, 4, 5, 6, 7, 8, 9, 8, 0]
But, when I give the value of d=2,
I get this error:
File ".\array_rotation.py", line 114, in <module>
arr[j]=arr[j+d]
IndexError: list index out of range
The same goes for different arrays too, I get a correct answer for the array according to the 'd' value.
The other array: arr = [1,2,3,4,5,6,7,8,9,10,11,12], d=2 -> I get perfect answer: [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2]
But with d=5 -> Again, I get list index out of range error.
I don't know where I have gone wrong - some test cases work and some do not.

Iterative summation

I'm trying to write a python code that allows me to iteratively sum up the average values of three elements of a list, starting with the third element and its two predecessors. Let me give you an example:
list = [1, 2, 3, 4, 5, 6, 7]
I want to calculate the following:
sum_of_average_values = sum(1, 2, 3)/3 + sum(2, 3, 4)/3 + sum(3, 4, 5)/3 + sum(4, 5, 6)/3 + sum(5, 6, 7)/3
Since I'm quite new to programming I couldn't find an effective way of putting this into a function.
You can do in this way:
a = [1,2,3,4,5,6,7]
sum_of_average_values = 0
for i in range(0,len(a)-2):
sum_of_average_values += sum(a[i:i+2])/3
print(sum_of_average_values)
You could use rolling from pandas.
import pandas as pd
num_list = [1, 2, 3, 4, 5, 6, 7]
average_sum = sum(pd.Series(num_list).rolling(3).mean().dropna())
print(average_sum)
Many ways to achieve this, one way is recursively.
The function averages the last three elements of a list and adds the result to the result generated by the function with a list lacking the last element. Continues like this until the list is shorter than 3.
def fn(l):
if len(l) < 3:
return 0
return sum(l[-3:])/3 + fn(l[:-1])
print(fn([1, 2, 3, 4, 5, 6, 7]))
Another solution where you can specify the amount of elements you want to sum up and average:
l = [1, 2, 3, 4, 5, 6, 7]
def sum_avg(l, n):
res = 0
for i in range(n-1, len(l)):
res += sum([l[j] for j in range(i, i-n, -1)])/n
return res
print(sum_avg(l, 3))
--> 20.0
Mathematically, this would could be obtain by averaging the sums of 3 sublists:
L = [1, 2, 3, 4, 5, 6, 7]
r = (sum(L) + sum(L[1:-1]) + sum(L[2:-2]))/3 # 20.0
and can be generalized to a window size of w:
w = 3
r = sum(sum(L[p:-p or None]) for p in range(w)) / w
It can also be implemented without the overhead of generating sublists by using item positions to determine the number of times they are added to the total:
r = sum(n*min(i+1,len(L)-i,w) for i,n in enumerate(L)) / w
This would be the most memory-efficient of the 3 methods because it use an iterator to feed data to the sum function and only goes through the data once.
Detailed explanation:
Since all the averages that are added together are a division by 3, we can produce the total sum and divide by 3 at the end
the number at the first and last positions are added once
the number at the second and penultimate positions are added twice
The numbers from the third position up to the antepenultimate will be added 3 times
visually:
(1 + 2 + 3) / 3
(2 + 3 + 4) / 3
(3 + 4 + 5) / 3
(4 + 5 + 6) / 3
(5 + 6 + 7) / 3
(1x1 + 2x2 + 3x3 + 4x3 + 5x3 + 6x2 + 7x1) / 3 = 20.0
n = 1 2 3 4 5 6 7 # value
* = 1 2 3 3 3 2 1 # multiplier (times added)
-------------------------
(2, 4, 9, 12, 15, 12, 7) / 3 = 20.0
i = 0 1 2 3 4 5 6 # index
1 2 3 3 3 2 1 # min(i+1,len(L)-i,w) = multiplier
You can do in one line using list comprehension as:
n = 3
avg = sum( [ sum(lst[i:i+n])/n for i in range(0, len(lst) - (n - 1)) ] )
print(avg) # 20.0

Use a custom order in range function Python

I have been struggling with this quite a bit, and was wondering if there is a solution for this.
I would like to use the range(start,stop,step) function in Python, but I would like to use a different order than what the normal functionalities allow. From what I understand the range function can do 3 things:
0, 1, 2, 3 etc
10, 9, 8, 7 etc
2, 4, 6, 8 etc
Now I am looking for the following order:
0, 10, 1, 9, 2, 8, 3, 7 etc
In this case 10 in the len(df), so the last row of the df.
You can create a generator to do that:
def my_range(n):
"""Yields numbers from 0 to n, in order 0, n, 1, n-1..."""
low = 0
high = n
while low <= high:
yield low
if high != low:
yield high
low += 1
high -= 1
Some examples:
print(list(my_range(10)))
# [0, 10, 1, 9, 2, 8, 3, 7, 4, 6, 5]
for i in my_range(5):
print(i)
0
5
1
4
2
3
This will provide every number in the interval exactly once, and lazily, just as range.
To answer the question in your comment:
if you want to mix the numbers in your_list = [1,3,4,5,7,9,10,12,13,14], you can just use this function to generate the indices:
your_list = [1,3,4,5,7,9,10,12,13,14]
for index in my_range(len(your_list)-1):
print(your_list[index], end=' ')
# 1 14 3 13 4 12 5 10 7 9
or you could build a new list in the mixed order:
new = [your_list[index] for index in my_range(len(your_list)-1)]
print(new)
# [1, 14, 3, 13, 4, 12, 5, 10, 7, 9]
range just has start, stop, step params. But you can achieve what you want by zipping two ranges together along with the chain.from_iterable function:
from itertools import chain
for val in chain.from_iterable(zip(range(11), range(10, -1, -1))):
print(val)
# 0 10 1 9 2 8 3 7 4 6 5 5 6 4 7 3 8 2 9 1 10 0
Note this solution repeats values, if you want no repeated values, then a generator is the way to go.
To keep things simple and clear the range function cannot do this.
Since it only allows to either increment or decrement at once.
but this can be achieved with loops and variables.
this is how to do it
for i in range(0,11):
print(i,10-i,end=" ")
this code will do it.

How can I sum every n array values and place the result into a new array? [duplicate]

This question already has answers here:
Sum slices of consecutive values in a NumPy array
(5 answers)
Closed 3 years ago.
I have a very long list of array numbers I would like to sum and place into a new array. For example the array:
[1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8]
would become:
[6,15,16,6,15,x]
if I was to sum every 3.
I cannot figure out how to go about it. I think possibly one problem is I do not know the length of my array - I do not mind losing the bottom bit of data if necessary.
I have tried the numpy.reshape function with no success:
x_ave = numpy.mean(x.reshape(-1,5), axis=1)
ret = umr_sum(arr, axis, dtype, out, keepdims)
I get an error:
TypeError: cannot perform reduce with flexible type
Cut the array to the correct length first then do a reshape.
import numpy as np
N = 3
a = np.array([1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8])
# first cut it so that lenght of a % N is zero
rest = a.shape[0]%N
a = a[:-rest]
assert a.shape[0]%N == 0
# do the reshape
a_RS = a.reshape(-1,N)
print(a_RS)
>> [[1 2 3]
[4 5 6]
[7 8 1]
[2 3 4]
[5 6 7]]
then you can simply add it up:
print(np.sum(a_RS,axis=1))
>> [ 6 15 16 9 18]
You can use a list comprehension do this:
ls = [1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8]
res = [sum(ls[i:i+3]) for i in range(0, len(ls), 3)]
[6, 15, 16, 9, 18, 8]
This will result in all the numbers being included in the resulting sum. If you don't want this to happen, then you can just check for it and replace the last sum with whatever value you want:
if (len(ls)%3) != 0:
res[-1] = 'x'
[6, 15, 16, 9, 18, 'x']
Or remove it entirely:
if (len(ls)%3) != 0:
res[:] = res[:-1]
[6, 15, 16, 9, 18]
Why don't you just simply use a list comprehension? E.g.
my_list = [1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8]
len_list = len(my_list) - len(my_list) % 3 # ignore end of list, s.t., only tuples of three are considered
[my_list[i] + my_list[i+1] + my_list[i+2] for i in range(0, len_list, 3)]

How to return list with negative integer in the program?

sum_of_n takes an integer n and returns a List of length abs(n) + 1.
The List/Array contains the numbers in the arithmetic series produced by taking the sum of the consecutive integer numbers from 0 to n inclusive.
Example
5 -> [0, 1, 3, 6, 10, 15]
-5 -> [0, -1, -3, -6, -10, -15]
7 -> [0, 1, 3, 6, 10, 15, 21, 28]
def sum_n(n):
a=n+1
x=0
b=0
list1=[]
for x in range(0,a):
b=(x*(x+1)*0.5)
list1.append(int(b))
return list1
print sum_n(5)
print sum_n(-5)
----output------
[0, 1, 3, 6, 10, 15]
[]
please explain me how can I return list with negative integer??
For negative integers, you need to use a negative step in your range(). So:
if a < 0:
step = -1
else:
step = 1
for x in range(0, a, step):
Now, in your calculation of b, you're adding 1 to x. This also needs to be changed to -1 when doing negative numbers. So you can just throw step in where you had 1.
Also, there's a difference between multiplying by 0.5 and dividing by 2 when dealing with negative numbers, and to get the result you're looking for you want the latter. So your calculation of b should now be:
b = x * (x + step) // 2
As a bonus, this will always be an integer, so you don't need the int(b) later (though it won't hurt).
I think it's not an issue with the return, but that your list is actually empty. Did you mean to take the absolute value of n before assigning it to a?
You could add a print statement in your loop to see what it's doing.
#if a < 0:
a = -5 #just defined the variable for easy explanation
y = 0
list1 = [0]
for x in range (1,abs(a)+1):
for h in range(x+1):
y -= h #<---- here
list1.append(y)
y = 0
print (list1)
Output
>>>
[0, -1, -3, -6, -10, -15]
>>>
Just minest instead of sum.

Categories

Resources