Split python list of booleans - python

I have a list
[True, False, False, True, True]
I need to receive
[[True],[True, True]]
Pleace help me with ideas how to do this 'pythonicly'.
Thank you

You can use itertools.groupby to accomplish this. Essentially it will group consecutive runs of True and False respectively, then just keep the groups of True using a list comprehension.
>>> from itertools import groupby
>>> values = [True, False, False, True, True]
>>> [list(g) for k, g in groupby(values) if k]
[[True], [True, True]]

Related

Combining boolean masks, why is in Python: [False, True] and [True, False] == [True, False] [duplicate]

This question already has answers here:
What is Truthy and Falsy? How is it different from True and False?
(8 answers)
Closed 2 years ago.
I was busy with combining masks and it strikes me that:
>>> [False, True] and [True, False]
[True, False]
and
>>> [True, False] and [False, True]
[False, True]
Why is this the case? Why shouldn't I expect it to be [False, False] in both cases?
I also think this is why np.logical_and() exists in Numpy:
>> np.logical_and([True, False], [False, False])
array([False, False])
This is the same reason why:
>>> (1,2) and (3,4)
(3, 4)
You need to understand that this is not doing element-wise comparison as opposed to np.logical_and.
The way and works is, if you have a and b, it checks whether a is False, if yes, return a else return b, does not matter what the value of b is.
In your case [False, True] is not False:
>>> bool([False, True])
True
Because it is a non-empty list, even [False, False] is True.
So in the case of [False, True] and [True, False], it checks to see whether [False, True] is False, which it is not, so it returns the second value. Same for the other case.
A python implementation of the and or logic would be:
def AND(first, second):
if bool(first) == True:
return second
else:
return first
def OR(first, second):
if bool(first) == True:
return first
else:
return second

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]

Getting True values in a boolean list from indices - 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)))

Python 2d array boolean reduction

I've got a 2D array comprised of boolean values (True,False). I'd like to consolidate the array to a 1D based on a logical function of the contents.
e.g.
Input:
[[True, True, False],
[False, False, False],
[True, True, True]]
Output (logical AND):
[False,
False,
True]
How would this be done without a loop ?
You can use Python's built-in all method with a list-comprehension:
[all(x) for x in my_list]
If that's still too loopy for you, combine it with map:
map(all, my_list)
Note that map doesn't return a list in Python 3. If you want a list as your result, you can call list(map(all, my_list)) instead.
You can do this without NumPy too. Here is one solution using list comprehension. Explanation: It will loop over sub-lists and even if one of the items in each sub-list is False, it outputs False else True.
inp = [[True, True, False],[False, False, False],[True, True, True]]
out = [False if False in i else True for i in inp]
print (out)
# [False, False, True]
Alternative (less verbose) as suggested by Jean below:
out = [False not in i for i in inp]
I'm assuming you want to apply logical ANDs to the rows. You can apply numpy.all.
>>> import numpy as np
>>> a = np.array([[True, True, False], [False, False, False], [True, True, True]])
>>> a
array([[ True, True, False],
[False, False, False],
[ True, True, True]])
>>>
>>> np.all(a, axis=1)
array([False, False, True])
For a solution without numpy, you can use operator.and_ and functools.reduce.
>>> from operator import and_
>>> from functools import reduce
>>>
>>> lst = [[True, True, False], [False, False, False], [True, True, True]]
>>> [reduce(and_, sub) for sub in lst]
[False, False, True]
edit: actually, reduce is a bit redundant in this particular case.
>>> [all(sub) for sub in lst]
[False, False, True]
does the job just as well.
You can do this with numpy with the numpy.all function:
>>> import numpy as np
>>> arr = np.array([[True, True, False],
... [False, False, False],
... [True, True, True]]
... )
>>> np.all(arr, axis=1)
array([False, False, True])
Here thus the i-th element is True if all elements of the i-th row are True, and False otherwise. Note that the list should be rectangular (all sublists should contain the same number of booleans).
In "pure" Python, you can use the all function as well, like:
>>> data = [[True, True, False], [False, False, False], [True, True, True]]
>>> list(map(all, data))
[False, False, True]
This approach will work as well if the "matrix" is not rectangular. Note that for an empty sublist, this will return True, since all elements in an empty sublist are True.
You can also do this with map and reduce:
from functools import reduce
l = [[True, True, False],
[False, False, False],
[True, True, True]]
final = list(map(lambda x: reduce(lambda a, b: a and b, x), l))
print(final)
# [False, False, True]
The benefit here is that you can change the reduce function to something else (say, an OR or something more adventurous).

Python list of booleans comparison gives strange results

I try:
[True,True,False] and [True,True,True]
and get
[True, True True]
but
[True,True,True] and [True,True,False]
gives
[True,True,False]
Not too sure why it's giving those strange results, even after taking a look at some other python boolean comparison questions. Integer does the same (replace True -> 1 and False ->0 above and the results are the same). What am I missing? I obviously want
[True,True,False] and [True,True,True]
to evaluate to
[True,True,False]
Others have explained what's going on. Here are some ways to get what you want:
>>> a = [True, True, True]
>>> b = [True, True, False]
Use a listcomp:
>>> [ai and bi for ai,bi in zip(a,b)]
[True, True, False]
Use the and_ function with a map:
>>> from operator import and_
>>> map(and_, a, b)
[True, True, False]
Or my preferred way (although this does require numpy):
>>> from numpy import array
>>> a = array([True, True, True])
>>> b = array([True, True, False])
>>> a & b
array([ True, True, False], dtype=bool)
>>> a | b
array([ True, True, True], dtype=bool)
>>> a ^ b
array([False, False, True], dtype=bool)
Any populated list evaluates to True. True and x produces x, the second list.
From the Python documentation:
The expression x and y first evaluates x; if x is false, its value is returned; otherwise, y is evaluated and the resulting value is returned.
You're getting the second value returned.
P.S. I had never seen this behavior before either, I had to look it up myself. My naive expectation was that a boolean expression would yield a boolean result.
and returns the last element if they all are evaluated to True.
>>> 1 and 2 and 3
3
The same is valid for lists, which are evalueted to True if they are not empty (as in your case).
[True, True, False] is being evaluated as a boolean (because of the and operator), and evaluates to True since it is non-empty. Same with [True, True, True]. The result of either statement is then just whatever is after the and operator.
You could do something like [ai and bi for ai, bi in zip(a, b)] for lists a and b.
As far as I know, you need to zip through the list. Try a list comprehension of this sort:
l1 = [True,True,False]
l2 = [True,True,True]
res = [ x and y for (x,y) in zip(l1, l2)]
print res
Python works by short-circuiting its boolean and gives the result expression as the result.
A populated list evaluates to true and gives the result as the value of the second list. Look at this, when I just interchanged the position of your first and second list.
In [3]: [True,True,True] and [True, True, False]
Out[3]: [True, True, False]

Categories

Resources