replacing random list entries with 0 - python

Hellow. I have some trouble with this question:
i have a list, for example a=[1,4,5,7,10]
i need another list with randomly chosen elements from a (b = np.random.choice(a,3,replace=False) -> b = [4,7,10]
But the length of the b must be the same as len(a). I guess i confuse someone with that text, so here are example :
1. `a = [1,4,5,7,10]`
2. `b = [0,4,0,7,10]`
so, the elements that wasn't chosen must be zeros.
Any suggestions would be appreciated

Reverse the question to "replacing random list entries with 0". Then the question becomes how to decide for any value whether to set it to 0 or not. Here we're using a certain random chance per value; you'll want to substitute that with whatever other specific criterion you have:
import random
a = [1,4,5,7,10]
b = [0 if random.randint(0, len(a)) < 2 else i for i in a]

There'll be better solutions, but this can work:
import numpy as np
a = np.array([1,4,5,7,10])
b = np.random.choice(np.arange(len(a)), 3, replace=False)
out = np.zeros(len(a), dtype=np.int)
out[b] = a[b]
print(out)
Note that I'm using choice on the list of indices into a, not the actual values of a.

import random
a = [1, 4, 5, 7, 10]
b = random.sample(a, len(a))
for i in range(len(b)):
if b[i] != a[i]:
b[i] = 0
print('a:', a)
print('b:', b)

Related

How to make a list comprehesion with enumerate while reseating a variable in python

Let's say I want to get the the number of jumps of each consecutive 1's in a binary string of say, 169, which is 10101001.
The answer then it'd be 3, 2, 2 because when the algorithm starts at the most right digit of the binary number needs to move thrice to the left to reach the next 1, twice to get the next 1 and so on.
So the algorithm should have a counter that starts at 0, increments in one while finds 0's and reset each time it reaches a 1.
I need the output to be in form of a list using list comprehesion.
This is what I got so far:
number = 169
list = []
c = 1
for i in bin(number>>1)[:1:-1]:
if i == '1':
list.append(c)
c = 0
c += 1
The algorithm indeed works but the idea is to transform it into one line code using list compreshesion. I think that there should be one way to do it using enumerate().
Just like:
n = 169
list = [i for i, c in enumerate(bin(number>>1)[:1:-1], 1) if c == '1']
The problem is that the output will be [3, 5, 7] instead of [3, 2, 2] because the i (index variable) didn't reset.
I'm looking for an asnwer that isn't just straight list[a+1] - list[a] but more elegant and efficient solution.
Here's a one-liner for this problem that's most probably not readable.
s = "10101001"
result = [p - q for p, q in zip([index for index, a in enumerate(s[::-1]) if a == "1"][1:], [index for index, b in enumerate(s[::-1]) if b == "1"][:s.count("1")-1])]
You can use groupby here:
bs = "10101001"
result = [
sum(1 for _ in g) + 1 # this can also be something like len(list(g)) + 1
for k, g in groupby(reversed(bs))
if k == "0"
]
You cannot really do this easily with just the list comprehension, because what you want cannot be expressed with just mapping/filtering (in any straightforward way I can think of), but once you have a grouping iterator, it simply becomes suming the length of "0" runs.
you can easily do this with a regex pattern
import re
out = [len(i) for i in re.findall("0*1", num)]
output
print(out)
>>> [3, 2, 2]

how to see if there is a value in a list that is between two values from another list

I have two lists
a = [1, 4, 12]
b = [2, 13]
I want to know if values in list b are between two values in list a
So, in this case, 2 will fall between 1 and 4. 13 will not fall between any numbers.
I have tried bisect function, but I couldn't get it work. I was able to use it with a single value and a list, but not two lists.
Maybe there's some subtlety that I do not get, but unless I am mistaken, you only have to check whether the elements are between the min and max from a. This is independent of whether the elements in a are sorted, or whether the values from b have to be between consecutive values from a. As long as they are between the min and max, there has to be a "segment" in a those values are in.
>>> a = [1, 4, 12]
>>> b = [2, 13]
>>> n, m = min(a), max(a)
>>> [n < x < m for x in b]
[True, False]
That is, of course, only if (a) you do not need which numbers they are in between, and (b) if not all values in b have to be in the same interval.
If you think I missed something, please comment.
It really depends on what you want it to return. I wrote a code that will return the first pattern that it finds, but with some changes I'm sure it would not be difficult to return all combinations.
def get_between(a, b):
a, b = sorted(a), sorted(b)
for b_value in b:
smaller = None
greater = None
for a_value in a:
if b_value > a_value:
smaller = a_value
elif b_value < a_value:
greater = a_value
if smaller and greater:
return f"{b_value} is between {smaller} and {greater}"
return "There is no such combination"
a = [1, 4, 12]
b = [2, 13]
print(get_between(a, b))
The output on that case will be 2 is between 1 and 4, but you can adapt the return value to be whatever you want.
You can keep two running indices to get a list of all elements that fall between values:
def get_between(arr1, arr2):
# first sort the arrays
arr1 = sorted(arr1)
arr2 = sorted(arr2)
# keep two indices into them
i1 = 0
i2 = 0
# keep track of the values between two values
ret = []
while i1 < len(arr1) - 1 and i2 < len(arr2):
# we're too small to be between a value
# so we should increase the second index
if arr2[i2] < arr1[i1]:
i2 += 1
# we're too large to be between a value
# so we should increase the first index
elif arr2[i2] > arr1[i1 + 1]:
i1 += 1
# we are between a value
# so we should append to the return array
# and move on to the next element
else:
ret.append(arr2[i2])
i2 += 1
return ret
get_between([1, 4, 12], [2, 8, 13]) # [2, 8]
If you don't care much about performance, here's a pythonic solution-
def betwn(rangelist, valuelist):
# Get list of all ranges between each consecutive number of rangelist
rgs = [range(rangelist[n], rangelist[n + 1]) for n in range(len(rangelist) - 1)]
# A function to check whether a given element exists between 2 consecutive numbers of rangelist
verifyfunc = lambda e: any(e in r for r in rgs)
# Return the qualifying elements from valuelist
return [e for e in valuelist if verifyfunc(e)]
Output
>>> betwn([1, 4, 12], [2, 13])
[2]

How to repeat a operation in for loop n times

The first input of following code is a single value like a=3, and second input is an array consisting of pairs of values like: B = [[1000, 1], [1000, 3], [999, 4]]. If the first value of each pair is even then I want the corresponding output value to be based on some specific calculation as shown in the code; if the first value is odd, there is another calculation as shown in code. The second value in the pair is the number of times I'd like to repeat the calculation for the pair. Calculations in the example should be repeated 1, 3 and 4 times for pairs 1, 2 and 3, respectively.
I am not sure how to repeat the calculation.
import numpy as np
a = np.array(input(), dtype=int)
B = []
for i in range(a):
b = np.array(input().split(), dtype=int)
B.append(b)
B = np.array(B)
C = []
for i in range(a):
if B[i, 0] % 2==0:
c = (B[i, 0] - 99) * 3
C.append(c)
else:
if B[i, 0] % 2 == 1:
d = (B[i, 0] - 15) * 2
C.append(d)
Ignoring the input, let's say you have an array
B = np.array([[1000, 1], [1000, 3], [999, 4]])
You can perform selective computations using a mask. The quickest way to type is probably using np.where:
C = np.where(B[:, 0] % 2, 2 * (B[:, 0] - 15), 3 * (B[:, 0] - 99))
This is a bit inefficient since it computes both values for each element. A much more efficient, but uglier, method would be to do everything in-place:
b = B[:, 0]
mask = (b % 2 == 0)
C = np.empty_like(b)
np.subtract(b, 99, out=C, where=mask)
np.subtract(b, 15, out=C, where=~mask)
np.multiply(C, 3, out=C, where=mask)
np.multiply(C, 2, out=C, where=~mask)
Numpy then provides the repeat function to do the repetition after you've computed the output values:
C = np.repeat(C, B[:, 1])
You can write the whole thing as a one-liner:
C = np.repeat(np.where(B[:, 0] % 2, 2 * (B[:, 0] - 15), 3 * (B[:, 0] - 99)), B[:, 1])
Probably a case for nested for loops. You have your outer loop, then loop through your calculations a certain number of times. So, from your example, try something like:
for i in range(a):
for x in range(B[i][1]):
if B[i][0] % 2 == 0:
B[i][0]=(B[i][0]-99)*3
else:
B[i][0]=(B[i][0]-15)*2
C.append(B[i][0]
Edited: If you want to repeat on the same value, just put it back into B and then append the value of that element of B back into C
Some other notes, not really related to your question but since the number will either be even or odd, you don't need the second if statement inside your else. If you really do need to explicitly check another condition, use Python's elif statement, short for else if which will only check the condition if none of the previous conditions were matched.

Python - List index out of range, "for" loop

I don't get how a "for" loop that iterates through the elements of a list can be out of range.
First part seems to be okay as I can print it.
import random
def random_list(n):
l = []
for i in range(0,n):
l.append(random.randint(0,n))
return l
def maximum(n):
x = 0
b = random_list(n)
for i in b:
if b[i] > x:
x = b[i]
print (maximum(10))
This:
for i in b:
if b[i] > x:
x = b[i]
Iterates over the elements of b, not the indices. Change it to
for i in b:
if i > x:
x = i
You also need to return something from your function, probably x.
Considering that you know how to iterate over a list in python, the error could be due to randint, which generates an integer in the interval [low, high]. This means high is a possible output, while the highest index in your program is high - 1.
For example,
random.randint(0, 0)
gives 0.
Similarly, random.randint(10) can return 10.
If you don't understand how to iterate over a list in Python, consider a simple example:
Take the list below:
myList = [1, 3, 5, 7, 9]
Now, there are two ways to iterate over the list:
Directly accessing elements:
for element in myList:
print(element, end=" ")
This gives the output:
1 3 5 7 9
Accessing elements using indices
for idx in range(len(myList)):
print(idx, ":", myList[idx], end=" ")
This gives the output:
0:1 1:3 2:5 3:7 4:9

Getting difference from all possible pairs from a list Python

I have an int list with unspecified number. I would like to find the difference between two integers in the list that match a certain value.
#Example of a list
intList = [3, 6, 2, 7, 1]
#This is what I have done so far
diffList = []
i = 0
while (i < len(intList)):
x = intList[i]
j = i +1
while (j < len(intList)):
y = intList[j]
diff = abs(x-y)
diffList.append(diff)
j += 1
i +=1
#Find all pairs that has a difference of 2
diff = diffList.count(2)
print diff
Is there a better way to do this?
EDIT: Made changes to the codes. This is what I was trying to do. What I want to know is what else can I use besides the loop.
seems like a job for itertools.combinations
from itertools import combinations
for a, b in combinations(intList, 2):
print abs(a - b)
You could even turn this one into a list comprehension if you wanted to :)
[abs(a -b) for a, b in combinations(intList, 2)]
int_list = [3, 6, 2, 7, 1]
for x in int_list:
for y in int_list:
print abs(x - y)

Categories

Resources