Finding an index in a list using 2 lists - python-3.x

Im trying to find the index of each 1 that is at the end of each group(sequence) of 1s. The output for the example below should be [17, 12, 9, 5, 1].
I can find the 1 at index 17 using the formula below but I also need to find the 1 at index 12. (i.e. it's the last instance of 1 in each sequence (or group) of 1s)
list = [1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0]
index_list1 = [i for i, v in enumerate(list) if v == 1]
index_list0 = [i for i, v in enumerate(list) if v == 0]
val1 = None
for i in index_list1[::-1]:
if i < index_list0[-1]:
val1 = i
break
else:
val1 = index_list1[-1]
if val1 is not None:
index1 = val1

You can simply use a conditional list comprehension:
my_list = [1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0]
results = [i for i, value in enumerate(my_list) if value == 1 and (my_list+[0])[i+1] != 1]
print(results)
this will print
[1, 5, 9, 12, 17]
The reason to append a [0] is to take care of cases where the original list ends with a 1.

Related

Have two lists blist with values and alist with indexes how do i change the value of Alist to 0 based on the index position given in Blist in pytho?

alist = [8,7,4,2]
blist = [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
how do I replace the values in blist with the value 0 for the list of indexes given in alist?
for i,j in enumerate(blist):
if i==alist:
blist[alist] == 0
many problems: that's alist you want to loop, == only makes tests, you can't use a list as an index in regular python (blist[alist])
alist = [8,7,4,2]
blist = [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
for index in alist:
blist[index] = 0
print(blist)
>>> [1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]

Replace values in a list based on condition of previous value

I would like to modify a list that has 3 different numbers [0, 1, 2]
Each 0 should be replaced with either the last 1 or 2 value depending on which was most recent during the iteration.
Is it possible to create the new list using a list comprehension?
I know I can use a for loop and just record the last 1 or 2 and append the values to the new list but I prefer the most pythonic way.
list = [1, 1, 2, 1, 0, 0, 1, 0, 2, 0, 0]
new_list = [1, 1, 2, 1, 1, 1, 1, 2, 2, 2]
I was using this but then realised that after 2 0s in a sequence it would start recording 0s again.
new_list = [list[index-1] if list[index] == 0 else value for index,value in enumerate(list)]
Starting in python 3.8 you now have the walrus operator := which can assign values as part of an expression and works in list comprehensions. You just need to decide what the first value will be if the list starts with 0 since there is no previous value:
alist = [1, 1, 2, 1, 0, 0, 1, 0, 2, 0, 0]
j = 0
[j:= i if i else j for i in alist]
# [1, 1, 2, 1, 1, 1, 1, 1, 2, 2, 2]
Perform that just with a list comprehension could be a little weird, so here my solution (without creating a new list):
my_list = [1, 1, 2, 1, 0, 0, 1, 0, 2, 0, 0]
last_not_zero = 0
for index, number in enumerate(my_list):
if number!=0:
last_not_zero = number
else:
my_list[index] = last_not_zero
print(my_list)
And you'll get:
[1, 1, 2, 1, 1, 1, 1, 1, 2, 2, 2]
If you have a large list or you are using Pandas in your code,
import pandas as pd
s = pd.Series(list)
s.replace(0, pd.np.nan).ffill().to_list()
Output
[1, 1, 2, 1, 1, 1, 1, 1, 2, 2, 2]
NOTE: If you are not using pandas/numpy in your code, then basic for loop would be the best way to do this. Advise using the above code only for large arrays with multiple manipulations.
How about this
last_value = 0
new_list = []
for value in list:
if value != 0:
last_value = value
new_list.append(value)
else:
new_list.append(last_value)
Depends on the condition.
In most cases, you can place the condition within the while loop in the if-else criteria statements.
If, say, you want to replace the content of a list if the previous value was
something,
size = len(list)
while True:
index = index + 1
if index!=0 and index<size:
if list[index-1]==something:
list[index] = value to be replaced
if index == (size-1):
a = 0
for a in (0, (size-1)):
print(a,":",list(a))
break

Python: Converting Binary to Decimal

What I'm currently doing is a implementation of Genetic Algorithms. I have written my Crossover and mutation methods and now i'm currently writing my Fitness method.
I need to convert my list of 0s and 1s to decimal values for calculating distance.
My current output that I'm working with are a list of integer values of 1s and 0s. (Example below):
[[0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1], [0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1]]
<class 'list'>
I want to convert these numbers to their respected binary equivalent.
I have tried converting the list to groups of 4 and then calling a binaryToDecimal function to convert the bits to decimal values. However, Im getting an error 'TypeError: 'numpy.ndarray' object is not callable'.
I have summarized my code and this is what it looks like so far.
def converting_binary_to_decimal(L):
output = []
for l in L:
l = list(map(str, l))
sub_output = []
for j in range(0, len(l)-1, 4):
sub_output.append(int(''.join(l[j:j+4]), 2))
output.append(sub_output)
return output
def chunks(L, n):
for i in range(0, len(L), n):
yield L[i:i+n]
def fitness(child):
newList1=list(chunks(child[0], 4))
newList2=list(chunks(child[1], 4))
if __name__ == "__main__":
myFitness = fitness(afterMU)
A sample output of what i want is:
[[0, 13, 6, 8, 12, 8, 10, 9, 15], [0, 8, 7, 0, 4, 4, 1, 8, 15]]
Try this code.
def converting_binary_to_decimal(L):
output = []
for l in L:
l = list(map(str, l))
sub_output = []
for j in range(0, len(l)-1, 4):
sub_output.append(int(''.join(l[j:j+4]), 2))
output.append(sub_output)
return output
L = [[0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1], [0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1]]
converting_binary_to_decimal(L)
I think i figured it out.
x=[0, 1, 1, 0]
k = 4
n = len(x)//k
for i in range(n):
y = x[i*k:(i+1)*k]
y = [str(j) for j in y]
y = ''.join(y)
y = int(y,2)
print(y)
Thank you.

How to check the distance between a specific element an index? Python3

A = [1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0]
B = 9
I want to find out the distances between the index[9] (B) and each of it's closest's 1's. For example, If we look at list A, we see that index 9 is this:
A = [1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0]
^
I would like to figure out the distances between B(index 9) and it's nearest 1's. For example, the nearest 1's in this case would be this:
A = [1, 0, 0, 0, 1, 0, 0, 1, 0, B, 0, 0, 1, 0]
^ ^
So in this case the output would be:
>> [2, 3] ##Since the distance between 1, 0, B is 2 and the distance between B, 0, 0, 1 is 3.
So far I've come up with the following code:
def checkDistance(A, B):
for i in A:
if i == 1:
#Check if it is the closest to B
#Check distance
Sadly I'm a beginner in python and I am struggling to finish. Any help would be much appreciated :)
def distance(lst,index):
c=[i for i,j in enumerate(lst) if j==1]
for k,l in zip(c[:-1],c[1:]):
if k < index < l:
return [index-k, l-index]
a = [1, 0, 0, 0, 1, 0, 0, 1, 0, B, 0, 0, 1, 0]
b = 9
distance(a, b)
Out: [2, 3]
You could use the following function. In this case, to make the function more abstract, you needn't force the value for the comparison to be 1 in the function.
In the function below, you do a for loop starting at the position you specified (in Python indexes start at 0, not at 1) and finishing when the list finishes.
The if statement compares element with the value of the list at a given position i
def checkDistance(lst,index,element):
counter = 0
results = []
for i in range(index,len(lst)):
if lst[i] == element:
print("Detected element at distance: " + str(counter))
results.append(counter)
counter += 1
return results

Removing duplicates with no sets, no for loops, maintain order and update the original list

Ok, so I have to remove duplicates from a list and maintain order at the same time. However, there are certain conditions such as I'm not allowed to use set or for loops. Also when the function mustn't return a new list but update the original list. I have the following code, but it only works partially and yes I know I'm only checking once, but I'm not sure how to proceed further.
def clean_list(values):
i = len(values)-1
while i > 0:
if values[i] == values[i-1]:
values.pop(i)
i -= 1
return values
values = [1, 2, 0, 1, 4, 1, 1, 2, 2, 5, 4, 3, 1, 3, 3, 4, 2, 4, 3, 1, 3, 0, 3, 0, 0]
new_values = clean_list(values)
print(new_values)
Gives me the result:
[1, 2, 0, 1, 4, 1, 2, 5, 4, 3, 1, 3, 4, 2, 4, 3, 1, 3, 0, 3, 0]
Thanks
Try the following.
Using two while loops, the first will get your unique item, the second will then search through the rest of the list for any other matching items and remove them, maintaining order.
def clean_list(lst):
i = 0
while i < len(lst):
item = lst[i] # item to check
j = i + 1 # start next item along
while j < len(lst):
if item == lst[j]:
lst.pop(j)
else:
j += 1
i += 1
values = [1, 2, 0, 1, 4, 1, 1, 2, 2, 5, 4, 3, 1, 3, 3, 4, 2, 4, 3, 1, 3, 0, 3, 0, 0]
clean_list(values)
print(values)
# Output
[1, 2, 0, 4, 5, 3]
Update: Improved function to be faster as worst case the first one was O(n2)
def clean_list(lst):
seen = set()
i = 0
while i < len(lst):
item = lst[i]
if item in seen:
lst.pop(i)
else:
seen.add(item)
i += 1
values = [1, 2, 0, 1, 4, 1, 1, 2, 2, 5, 4, 3, 1, 3, 3, 4, 2, 4, 3, 1, 3, 0, 3, 0, 0]
clean_list(values)
print(values)
# Output
[1, 2, 0, 4, 5, 3]

Resources