Getting True values in a boolean list from indices - python - python

How do I compute the inverse of what is described here: Getting indices of True values in a boolean list ?
That above link always comes up when I try searching for "how to obtain the true values in a boolean list from integer indices," but it gives me the indices from the true values in a boolean list, which is the inverse of what I want...
For example, from:
t = [4, 5, 7]
count = 16
I want to obtain:
[False, False, False, False, True, True, False, True, False, False, False, False, False, False, False, False]
The values are all 0 indexed, as expected with Python.
I'm guessing that my question is a duplicate, but it's so annoying to not be able to find what I'm looking for every time I try to remember how to do this operation, I decided to ask a new question so my Google search will hopefully bring up this post next time.

You can use a list comprehension. I recommend you turn t into a set for O(1) lookup:
t_set = set(t)
res = [i in t_set for i in range(count)]

Use a list comprehension with conditions:
print([True if i in t else False for i in range(count)])
Shorter:
print([i in t else False for i in range(count)])

How about this:
In [6]: holderplace =[False for i in range(count)]
In [7]: for i in t:
...: holderplace[i-1]=True
...:
In [8]: holderplace
Out[8]:
[False,
False,
False,
True,
True,
False,
True,
False,
False,
False,
False,
False,
False,
False,
False,
False]
In [9]:

You could also try using map():
list(map(lambda x: x in t, range(count)))
# [False, False, False, False, True, True, False, True, False, False, False, False, False, False, False, False]
It might also be worth converting t to a set, since lookup is O(1) instead of O(N).
You could also use __contains__():
list(map(t.__contains__, range(count)))

Related

is there a more efficient way to make a grid for bool values

I am trying to make a grid to store bool variables kinda like mine sweeper and i would like to find a better way
So far i have a very inefficient way of just declaring like 15 lists with the values set to false like this
A = [False, False, False, False, False, False, False, False, False, False]
Is there a more efficient way to do this
You can efficiently create a list of the same value with:
A = [False]*15
However, more code is required to extend this into a grid. Instead, you could use NumPy to create a grid of False (True) values by using np.zeros (np.ones). For example, a 3x4 grid of False values can be created with:
grid = np.zeros((3, 4), dtype=bool)
>> [[False False False False]
>> [False False False False]
>> [False False False False]]
You might want to use a 2D array for that:
array = [
[False, False, False, False, False, False, False, False, False, False],
[False, False, False, False, False, False, False, False, False, False],
...
]
This can also be created using a list comp:
array = [[False] * 15 for _ in range(15)]

Efficient way to find elements in list out of order

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]

Finding False-True transitions in a numpy array

Given a numpy array:
x = np.array([False, True, True, False, False, False, False, False, True, False])
How do I find the number of times the values transitions from False to True?
For the above example, the answer would be 2. I don't want to include transitions from True to False in the count.
From the answers to How do I identify sequences of values in a boolean array?, the following produces the indices at which the values are about to change, which is not what I want as this includes True-False transitions.
np.argwhere(np.diff(x)).squeeze()
# [0 2 7 8]
I know that this can be done by looping through the array, however I was wondering if there was a faster way to do this?
Get one-off slices - x[:-1] (starting from the first elem and ending in second last elem) and x[1:] (starting from the second elem and going on until the end), then look for the first slice being lesser than the second one, i.e. catch the pattern of [False, True] and finally get the count with ndarray.sum() or np.count_nonzero() -
(x[:-1] < x[1:]).sum()
np.count_nonzero(x[:-1] < x[1:])
Another way would be to look for the first slice being False and the second one as True, the idea again being to catch that pattern of [False, True] -
(~x[:-1] & x[1:]).sum()
np.count_nonzero(~x[:-1] & x[1:])
I kind of like to use numpy method "roll" for this kind of problems...
"roll" rotates the array to left some step length : (-1,-2,...) or to right (1,2,...)
import numpy as np
np.roll(x,-1)
...this will give x but shifted one step to the left:
array([ True, True, False, False, False, False, False, True, False, False],
dtype=bool)
A False followed by a True can then be expressed as:
~x & np.roll(x,-1)
array([ True, False, False, False, False, False, False, True, False, False],
dtype=bool)

How do I find what index a True value is located at in an array contaning True and False values?

I have an np.array with True and False values in it. Something along the lines of this:
full=[False, False, False, False, False, False, False, False, False,
False, False, False, False, False, False, False, False, False,
False, False, False, False, False, False, True, False, False,
False, False, False, False, False, False, False, False, False]
There is a true value at the 24th position. I know that
b = np.where(full)
will print out something like this
(array([24]),)
but I am only interested in the number 24. Assuming that this True value can be at any place in the full array and that there can even be more than one True value in full, how do I retrieve the numbers in b?
edit: Trying to be more specific. Basically I am trying to take the value from b and put it into another np.array. If I enter b into a 1d array like so:
oar[b]
because b is not a number it sends back an error.
Also, just to reiterate, full is a numpy array and can have all true, no true, or multiple true values.
you can use argmax(arr) for the index of the first True value.
As pointed out by #Alok, if the result is zero you must then check if the first element of arr is False.

How to apply a logical operator to all elements in a python list

I have a list of booleans in python. I want to AND (or OR or NOT) them and get the result. The following code works but is not very pythonic.
def apply_and(alist):
if len(alist) > 1:
return alist[0] and apply_and(alist[1:])
else:
return alist[0]
Any suggestions on how to make it more pythonic appreciated.
Logical and across all elements in a_list:
all(a_list)
Logical or across all elements in a_list:
any(a_list)
If you feel creative, you can also do:
import operator
def my_all(a_list):
return reduce(operator.and_, a_list, True)
def my_any(a_list):
return reduce(operator.or_, a_list, False)
keep in mind that those aren't evaluated in short circuit, whilst the built-ins are ;-)
another funny way:
def my_all_v2(a_list):
return len(filter(None,a_list)) == len(a_list)
def my_any_v2(a_list):
return len(filter(None,a_list)) > 0
and yet another:
def my_all_v3(a_list):
for i in a_list:
if not i:
return False
return True
def my_any_v3(a_list):
for i in a_list:
if i:
return True
return False
and we could go on all day, but yes, the pythonic way is to use all and any :-)
By the way, Python has not tail recursion elimination, so don't try to translate LISP code directly ;-)
ANDing and ORing is easy:
>>> some_list = [True] * 100
# OR
>>> any(some_list)
True
#AND
>>> all(some_list)
True
>>> some_list[0] = False
>>> any(some_list)
True
>>> all(some_list)
False
NOTing is also fairly easy:
>>> [not x for x in some_list]
[True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False]
Of course, how you would use those results might require some interesting applications of DeMorgan's theorem.
Reduce can do this:
reduce(lambda a,b: a and b, alist, True)
As fortran mentioned, all is the most succinct way to do it. But reduce answers the more general question "How to apply a logical operator to all elements in a python list?"
The idiom for such operations is to use the reduce function (global in Python 2.X, in module functools in Python 3.X) with an appropriate binary operator either taken from the operator module or coded explicitly. In your case, it's operator.and_
reduce(operator.and_, [True, True, False])
Here's another solution:
def my_and(a_list):
return not (False in a_list)
def my_or(a_list):
return True in a_list
ANDing all elements will return True if all elements are True, hence no False in a list.
ORing is similar, but it should return True if at least one True value is present in a list.
As the other answers show, there are multiple ways to accomplish this task. Here's another solution that uses functions from the standard library:
from functools import partial
apply_and = all
apply_or = any
apply_not = partial(map, lambda x: not x)
if __name__ == "__main__":
ls = [True, True, False, True, False, True]
print "Original: ", ls
print "and: ", apply_and(ls)
print "or: ", apply_or(ls)
print "not: ", apply_not(ls)

Categories

Resources