I have a list a and I need to iterate from position 2 until its previous position 1.
# old index - 0 1 2 3 4
a = [1,2,3,4,5]
# new index - 2,3,4,0,1
# new value - 3,4,5,1,2
cnt = 0
while True:
for i in range(2,len(a)):
print(a[i])
for i in range(len(a)-2-1):
print(a[i])
break
I'm using 2 for loops but I believe there should be a better way to do it.
Let's assume we start with a list a = [1,2,3,4,5].
You can use collections.deque and its method deque.rotate:
from collections import deque
b = deque(a)
b.rotate(-2)
print(b)
deque([3, 4, 5, 1, 2])
Or, if you are happy to use a 3rd party library, you can use NumPy and np.roll:
import numpy as np
c = np.array(a)
c = np.roll(c, -2)
print(c)
array([3, 4, 5, 1, 2])
you can create a new list combining the elements after the particular value and before the particular value, let's say 3 in your case:
a = [1, 2, 3, 4, 5]
piv = a.index(3)
print(a[piv:] + a[:piv])
which gives you [3, 4, 5, 1, 2]
a = [1,2,3,4,5]
position = 2
for item in a[position:] + a[:position]:
print(item)
A base python based solution
a[2::] + a[:2:]
Gives
[3, 4, 5, 1, 2]
A generic version of the same would be
rotate_from = 2
a[rotate_from::] + a[:rotate_from:]
Write a function for rotate list,
In [114]: def rotate(lst, n):
...: return lst[-n:] + lst[:-n]
...:
In [115]: rotate(a,-2)
Out[115]: [3, 4, 5, 1, 2]
Related
I have two arrays of the same shape and now want to combine them by making every odd element and 0 one of the first array and every even one of the second array in the same order.
E.g.:
a = ([0,1,3,5])
b = ([2,4,6])
c = ([0,1,2,3,4,5,6])
I tried something including modulo to identify uneven indices:
a = ([0,1,3,5])
b = ([2,4,6])
c = a
i = 0
j = 2
l = 0
for i in range(1,22):
k = (i+j) % 2
if k > 0:
c = np.insert(c, i, b[l])
l+=1
else:
continue
I guess there is some easier/faster slicing option, but can't figure it out.
np.insert would work well:
>>> A = np.array([1, 3, 5, 7])
>>> B = np.array([2, 4, 6, 8])
>>> np.insert(B, np.arange(len(A)), A)
array([1, 2, 3, 4, 5, 6, 7, 8])
However, if you don't rely on sorted values, try this:
>>> A = np.array([5, 3, 1])
>>> B = np.array([1, 2, 3])
>>> C = [ ]
>>> for element in zip(A, B):
C.extend(element)
>>> C
[5, 1, 3, 2, 1, 3]
read the documentation of the range
for i in range(0,10,2):
print(i)
will print [0,2,4,6,8]
From what I understand, the first element in a is always first the rest are just intereleaved. If that is the case, then some clever use of stacking and reshaping is probably enough.
a = np.array([0,1,3,5])
b = np.array([2,4,6])
c = np.hstack([a[:1], np.vstack([a[1:], b]).T.reshape((-1, ))])
You could try something like this
import numpy as np
A = [0,1,3,5]
B = [2,4,6]
lst = np.zeros(len(A)+len(B))
lst[0]=A[0]
lst[1::2] = A[1:]
lst[2::2] = B
Even though I don't understand why you would make it so complicated
I am trying to write a code that compares two arrays ('a' and 'b)' and do something like that, getting the 'c' array:
a = [1, 2, 2, 3, 3, 5]
b = [1, 2, 3] (It is taken from 'a' randomly)
c = [2, 3, 5]
The problem I have is very simple since the algorithm is ok.
The code I am using is:
vetor1 = [1, 2, 2, 3, 3, 5]
vetor2 = sorted(random.sample(vetor1, 3))
inter = np.intersect1d(vetor1, vetor2)
cont_array2 = []
for i in range(len(inter)):
cont2 = 0
for j in range(len(vetor2)):
if inter[i]==vetor2[j]:
cont2 = cont2 + 1
cont_array2.append(cont2)
cont_array1 = []
for i in range(0,len(inter),1):
cont1 = 0
for j in range(0, len(vetor1), 1):
if inter[i]==vetor1[j]:
cont1 = cont1 + 1
cont_array1.append(cont1)
n_elements = np.subtract(cont_array1, cont_array2)
vetor2_1 = []
for i in range(len(n_elements)):
if n_elements[i]!=0:
vetor2_1.append(inter[i]*np.ones(n_elements[i]))
vetor2_2 = []
for data1 in vetor1:
if data1 not in inter:
vetor2_2.append(data1)
vetor3 = sorted(vetor2_1 + vetor2_2)
print(vetor3)
The result I am getting is:
[array([2.]), array([3.]), 5]
I imagine the problem is in:
vetor2_1.append(inter[i]*np.ones(n_elements[i]))
Because:
print(vetor2_1)
Gives me:
[array([2.]), array([3.])]
What should I do since I am not receving as answer [2, 3, 5]?
IIUC, you can turn all your algorithm into one line:
a = [1, 2, 2, 3, 3, 5]
b = [1, 2, 3]
c = [a.pop(a.index(i)) for i in b] #Works even with strings.
Output:
[2, 3, 5]
If you need to parametrize something, you can turn it into a function. This will work with sorted(random.sample(vetor1, 3)), but I didn't use it for replicability.
//generating a random index for array a, to take 3 elements out of it
my_random_int = random.randint(0,len(a)-2)
//popping the element out of the array to put them in b
for x in range(0,2):
b[x]=a.pop(my_random_int+x)
sources:
https://www.programiz.com/python-programming/methods/list/pop
https://www.edureka.co/blog/generate-random-number-in-python/
I need to create a random array of 6 integers between 1 and 5 in Python but I also have another data say a=[2 2 3 1 2] which can be considered as the capacity. It means 1 can occur no more than 2 times or 3 can occur no more than 3 times.
I need to set up a counter for each integer from 1 to 5 to make sure each integer is not generated by the random function more than a[i].
Here is the initial array I created in python but I need to find out how I can make sure about the condition I described above. For example, I don't need a solution like [2 1 5 4 5 4] where 4 is shown twice or [2 2 2 2 1 2].
solution = np.array([np.random.randint(1,6) for i in range(6)])
Even if I can add probability, that should work. Any help is appreciated on this.
You can create an pool of data that have the most counts and then pick from there:
import numpy as np
a = [2, 2, 3, 1, 2]
data = [i + 1 for i, e in enumerate(a) for _ in range(e)]
print(data)
result = np.random.choice(data, 6, replace=False)
print(result)
Output
[1, 1, 2, 2, 3, 3, 3, 4, 5, 5]
[1 3 2 2 3 1]
Note that data is array that has for each element the specified count, then we pick randomly from data this way we ensure that you won't have more elements that the specify count.
UPDATE
If you need that each number appears at least one time, you can start with a list of each of the numbers, sample from the rest and then shuffle:
import numpy as np
result = [1, 2, 3, 4, 5]
a = [1, 1, 2, 0, 1]
data = [i + 1 for i, e in enumerate(a) for _ in range(e)]
print(data)
result = result + np.random.choice(data, 1, replace=False).tolist()
np.random.shuffle(result)
print(result)
Output
[1, 2, 3, 3, 5]
[3, 4, 2, 5, 1, 2]
Notice that I subtract 1 from each of the original values of a, also the original 6 was change to 1 because you already have 5 numbers in the variable result.
You could test your count against a dictionary
import random
a = [2, 2, 3, 1, 2]
d = {idx: item for idx,item in enumerate(a, start = 1)}
l = []
while len(set(l) ^ set([*range(1, 6)])) > 0:
l = []
while len(l) != 6:
x = random.randint(1,5)
while l.count(x) == d[x]:
x = random.randint(1,5)
l.append(x)
print(l)
I'm trying to sum the elements of a list and then store the result of each sum in another list.
So far I have this:
array1 = [1, 2, 3, 4]
print(sum(int(i) for i in array1))
The output is 10.
But what I'm trying to do is something like this:
input = [1, 2, 3, 4]
output = [1, 3, 6, 10]
Do I need to store the value into the second list in each step?
If you're running Python 3.2 or higher, there is already a function for this, itertools.accumulate:
import itertools
input = [1,2,3,4]
output = list(itertools.accumulate(input))
If you're on a pre-3.2 version of Python, you can always borrow the equivalent code given in the accumulate documentation:
def accumulate(iterable, func=operator.add):
'Return running totals'
# accumulate([1,2,3,4,5]) --> 1 3 6 10 15
# accumulate([1,2,3,4,5], operator.mul) --> 1 2 6 24 120
it = iter(iterable)
try:
total = next(it)
except StopIteration:
return
yield total
for element in it:
total = func(total, element)
yield total
Using a list comprehension is probably not the easiest way. You could do this:
input = [1, 2, 3, 4]
output = []
total = 0
for i in input:
total += i
output.append(total)
This does what you want, but is maybe not that good to understand...
output = [sum(array1[:i+1]) for i in range(len(array1))]
You can also do it like this (which should be easier to understand):
i = 0
output = []
for item in array1:
i += item
output.append(i)
You might numpy useful if you are doing a lot if numeric operations, the cumsum method would do what you want here:
In [11]: import numpy as np
In [12]: array1 = np.array([1, 2, 3, 4])
In [13]: array1.cumsum()
Out[13]: array([ 1, 3, 6, 10])
It is easy to apply the same logic using python:
def cumsum(l):
it = iter(l)
sm = next(it, 0)
yield sm
for i in it:
sm += i
yield sm
Demo:
In [16]: array1 = [1, 2, 3, 4]
In [17]: list(cumsum(array1))
Out[17]: [1, 3, 6, 10]
I have a list of integers (from 0 to N) and I need to create a new list which contains the indexes of each integer in the first list.
That is, given
s = [4, 2, 6, 3, 0, 5, 1]
determine r such that s[r[i]] = i
r = [4, 6, 1, 3, 0, 5, 2]
My current solution is
r = [s.index(i) for i in xrange(len(s))]
Is there a better way?
I assume that each integer in S appears exactly once. Your current solution will work, the problem is that s.index performs an O(N) search, making this an O(N**2) operation.
For a large list, I would expect the following code to be faster since it is O(N)
# initialise the whole list with some value
r = [-1]*N
for j, s_j in enumerate(s):
r[s_j] = j
# if any element of r is still -1 then you know it did not appear in s
It seems like a dictionary would be better for this:
s = [4, 2, 6, 3, 0, 5, 1]
r = dict((v,i) for i,v in enumerate(s))
testing:
>>> for i,_ in enumerate(s):
... print i, s[r[i]]
...
0 0
1 1
2 2
3 3
4 4
5 5
6 6
Personally the approach you showed is great.
Either a dictionary would work - that would be my first try:
r = {v:i for i, v in enumerate(s)}
Or if you have to use a list another approach is:
r = [x[0] for x in sorted(enumerate(s), key=lambda v:v[1])]
Are you allowed to use numpy ?
>>> import numpy as np
>>> s = np.array([4, 2, 6, 3, 0, 5, 1])
>>> s.argsort()
array([4, 6, 1, 3, 0, 5, 2], dtype=int64)
i did a simple benchmark with the timit module #10^6 iterations - 5 repetitions.
DaveP : 1.16 +/- 0.04s
koblas: 7.02s +/- 0.04s
Jon Clements: 1.82 +/- 0.02s
Zero Piraeus: 6.04 +/- 0.4s
and last but not least:
r=s[:]
[r[s[i]] for i in s]
my suggestion: 1.11 +/- 0.03s