I expected the following 2 code-segments to be essentially equivalent.
return tuple(tuple( False if (i,j) in neighborhood else avail[i][j]
for i in range(len(avail)))
for j in range(len(avail[i])))
(False, False, True, True, True)
(False, False, True, True, True)
(False, False, True, True, True)
(False, False, True, True, True)
(True, True, True, True, True)
ls = [[val for val in row] for row in avail]
for i in range(len(avail)):
for j in range(len(avail[i])):
if (i,j) in neighborhood:
ls[i][j] = False
return ls
[False, False, False, False, True]
[False, False, False, False, True]
[True, True, True, True, True]
[True, True, True, True, True]
[True, True, True, True, True]
The one with the for-loops is "correct" (thats what I wanted). Why did the list comprehension-version swap the indexes?
You have your loops inverted in the first version. You are creating inner tuples looping over range(len(avail)) and outer tuples with a loop over range(len(avail[i])).
Your code is the equivalent (with lists instead of tuples) of this instead:
outer = []
for j in range(len(avail[i])):
inner = []
for i in range(len(avail)):
inner.append(False if (i,j) in neighborhood else avail[i][j])
outer.append(inner)
and relied on i still being assigned as a global. You can see this too when you indent your expression based on the parenthesis:
return tuple(
tuple(
False if (i,j) in neighborhood else avail[i][j]
for i in range(len(avail))
)
for j in range(len(avail[i]))
)
Reverse the loops (indented differently to communicate the grouping better):
return tuple(
tuple(False if (i,j) in neighborhood else avail[i][j] for j in range(len(avail[i])))
for i in range(len(avail)))
The above is the equivalent of:
outer = []
for i in range(len(avail)):
inner = []
for j in range(len(avail[i])):
inner.append(False if (i,j) in neighborhood else avail[i][j])
outer.append(inner)
You can simplify your code with using enumerate():
return tuple(
tuple(False if (i,j) in neighborhood else v for j, v in enumerate(row))
for i, row in enumerate(avail))
Related
Note: this is a working program, I just need to make it faster.
This is the nested for loop:
taf = []
for i in range(len(piou)):
counter = 0
for j in range(len(piou[i])):
if piou[i][j] == True:
counter = counter + 1
if counter == len(piou[i]):
taf.append(i)
I tried doing this:
taf = [i for i in range(len(piou))
if counter == len(piou[i])
for j in range(len(piou[i]))
if piou[i][j] == True]
but I can't figure out how to put the counter variable in between along with its increment.
Note: piou is a 2D tensor with boolean values and I am trying to find and append all the rows (i) index values to taf list which have all "true" column values.
piou looks like this:
tensor([[ True, True, True, True, False, False],
[ True, True, True, True, True, True],
[False, False, True, True, True, True],
[ True, True, False, False, True, True],
[ True, True, True, True, True, True]], device='cuda:0')
A loop where you're just incrementing a number can be replaced with sum(), but where that summation is just going to be compared with the length of the list, use all().
As well, avoid for i in range(len(seq)) ... i, seq[i], use for i, x in enumerate(seq) instead.
taf = [i for i, row in enumerate(piou) if all(row)]
Suppose I have a two-dimensional list mixed with True and False. I would like to create a function that gives me an additional parameter, which should be the number of elements to be output. The output should be like this:
For example, if I enter 3 as a number, the row and column in which 3 x True are located one after the other should be displayed.
So just the row and the first column
For example, in the list below:
3 x True in row: 1 and col: 3
lst = [[False, True, False, True, True, False],
[False, True, False, True, True, True],
[True, False, True, True, True]]
I've tried several options, but never found a solution. I have another small example here, but of course I get the wrong output:
def baz(count):
for row in range(len(lst)):
for col in range(len(lst[row])):
if lst[row][col] == lst[row][(col + count) % len(lst[row])] and lst[row][col] is True:
return (row, col)
print(baz(3))
You can use all to simplify the code, it returns True if all values in the iterable are True otherwise False.
lst = [[False, True, False, True, True, False],
[False, True, False, True, True, True],
[True, False, True, True, True]]
def baz(count):
for row in range(len(lst)):
if len(lst[row]) < count:
continue
for col in range(len(lst[row])-count+1):
if all(lst[row][col:col+count]):
return (row, col)
return None
print(baz(3))
print(baz(2))
prints -
(1, 3)
(0, 3)
Note that there can be multiple matches for a given count, so the function returns the first match found.
Also, for high values of count, above code is not optimal(since in each step we are doing O(count) work when we call all(). So in case you are worried about performance you can use the below function instead -
def baz(count):
for row in range(len(lst)):
if len(lst[row]) < count:
continue
prev_true = -1
for col in range(len(lst[row])):
if not lst[row][col]:
prev_true = col
continue
if col - prev_true == count:
return (row, col-count+1)
return None
I am trying to import the answer of a function. The function is this:
def flo(rate,length, interval, threshold):
data = [] #to create an empty list
new = [rate[i:i+ length] for i in range(0, len( rate)-len( rate) % length , length)]
for i in range(len(new )):
data.append('True')
print(data)
return
flo( rate,length, interval, threshold)
where I got the output:
[False]
[False, False]
[False, False, True]
[False, False, True, True]
[False, False, True, True, True]
[False, False, True, True, True, False]
[False, False, True, True, True, False, True]
[False, False, True, True, True, False, True, True]
[False, False, True, True, True, False, True, True, False]
Now I want to import this answer into another function. So I did:
import flow_rate as flow
z = flow.flow_rate ( rate, length, interval, threshold)
print(z)
But my output is:
None
Am I doing something wrong?
You simply put a return statement. There is not variable after return, so None is getting returned. It is as good as the returnstatement is not present in the function.
So you need to return the data:
return data
Given this list
[True, False, True, True, False, True, False, False]
I want to find all elements in that list that are False mixed between True elements. Meaning:
[True, True, True, True, True, False, False, False]
would yield nothing, and the list above should yield:
[1, 4]
I am currently just writing a loop which tries to remember the state walking that list backwards but I thought there might be a more efficient way. The index itself is not really needed as I am actually adding the elements which are unique to a list
Try this,
# zip both the array to create a tuple & yield those.
for index, (n, m) in enumerate(zip([True, False, True, False],
[True, True, True, True])):
if n != m:
print(index)
Output
(1,3)
enumerate
zip
maybe you can do it like this
test = [True, False, True, True, False, True, False, False]
start = None
found = None
end = None
for i in range(len(test)):
if test[i] is False:
if start is None:
start = i
else:
found = i
elif found is not None:
end = found
if start is not None and end is not None:
print(start)
print(end)
# Create the list
li = [True, False, True, True, False, True, False, False]
# iterate from front until the first True value and remove all the False values
for i in li:
if not i: li.pop()
if i: break
# Out: [True, False, True, True, False, True, False, False]
# Iterate from back until the first True value and remove all the False values
for i in reversed(li):
print(i)
if i: break
if not i: li.pop()
# Out: [True, False, True, True, False, True]
# Find the indices of remaining False values
[i for i,x in enumerate(li) if not x]
# Out: [1, 4]
I am trying to build long lists of boolean elements to be associated to trace visibility in plotly using the python api.
My input is:
list_true = list( np.ones(3, dtype=bool) )
list_false = list( np.zeros(3, dtype=bool) )
blocks = [1,2,3]
How should I define a loop that builds a list of lists so that the position of list_true blocks varies depending on the value of the index blocks[i]?. The ouput should be:
combination1 = list_true + list_false + list_false
combination2 = list_false + list_true + list_false
combination3 = list_false + list_false + list_true
that is:
combination1 = [
True, True, True,
False, False, False,
False, False, False,
]
combination2 = [
False, False, False,
True, True, True,
False, False, False,
]
combination3 = [
False, False, False,
False, False, False,
True, True, True,
]
import numpy as np
list_true = list(np.ones(3, dtype=bool))
list_false = list(np.zeros(3, dtype=bool))
blocks = [1,2,3]
combination = []
for i in blocks:
sub_combination = [list_false for k in range(3)]
sub_combination[i-1] = list_true
combination.append(sub_combination [0] + sub_combination [1] + sub_combination [2])
print('combination1')
print(combination[0])
print('combination2')
print(combination[1])
print('combination3')
print(combination[2])
If I understand you correctly and combination should be a list of lists (matrix basicly) you can do it like this (to solve it more elegantly I have not seperated the combination variables but made a list of combinations):
import numpy as np
list_true = list(np.ones(3, dtype=bool))
list_false = list(np.zeros(3, dtype=bool))
blocks = [1,2,3]
combination = []
for i in range(len(blocks)):
combination.append([list_true, list_true, list_true])
combination[i][i] = list_false
print(combination)
I found the solution to my issue, which changes with the length of the blocks list (as intended) and flattens the combined (nested) list into the desired result. Thanks to #Odame Prince for the tip.
import numpy as np
list_true = list(np.ones(3, dtype=bool))
list_false = list(np.zeros(3, dtype=bool))
blocks = ['A','B','C','D']
for i in range(len(blocks)):
combo_list = [list_false for k in range(len(blocks))]
combo_list[i] = list_true
flat_list = [item for sublist in combo_list for item in sublist]
print('\nCombination{}: {}'.format(i, flat_list) )
Returns:
Combination0: [True, True, True, False, False, False, False, False, False, False, False, False]
Combination1: [False, False, False, True, True, True, False, False, False, False, False, False]
Combination2: [False, False, False, False, False, False, True, True, True, False, False, False]
Combination3: [False, False, False, False, False, False, False, False, False, True, True, True]
You can also use this shorter version with insert:
list_true = np.ones(3, dtype=bool)
list_false = np.zeros(3, dtype=bool)
blocks = [1, 2, 3]
initial = [np.repeat(list_false, 2) for i in range(3)]
final = [np.insert(initial[b-1], (b-1)*3, list_true) for b in blocks]
You can define a generic function to insert a list at position of N and apply it to your true and false lists. The good thing is that you are not restricted to totally 3 lists as in your example. You can have as many lists as you wish (change user defined total n and use it as an argument of function put_true).
You can also give any list you want to the function. You can decide which one you are interested in (chose L_insert, the true list in your example) and which are those you will just use to fill the blanks (chose L2, the false list in your example).
import numpy as np
list_true = list(np.ones(3, dtype=bool) )
list_false = list(np.zeros(3, dtype=bool) )
blocks = [1,2,3]
# generic function to insert list L_insert among L2s
# which list to be inserted, to which position within how many lists
# can all be defined by user
def insert_list(L_insert, L2):
def insert_at_n(n_insert, n_total):
if n_total == 0:
return []
elif n_insert == 1:
return L_insert + insert_at_n(n_insert-1, n_total-1)
else:
return L2 + insert_at_n(n_insert-1, n_total-1)
return insert_at_n
put_true=insert_list(list_true, list_false)
total = 3 # if you want more false list to be appended, simply change this number
put_true_at_n = lambda n: put_true(n, total)
combination1 = put_true_at_n(1)
combination2 = put_true_at_n(2)
combination3 = put_true_at_n(3)
...
combinationn = put_true_at_n(n)
# an additional benefit is that you can simply apply it to a list of integers
# in order to automatize your work
print([put_true_at_n(n) for n in blocks])