This question already has answers here:
Python AND operator on two boolean lists - how?
(10 answers)
Closed 6 years ago.
Shouldn't the results be the same?
I do not understand.
[True,False] and [True, True]
Out[1]: [True, True]
[True, True] and [True,False]
Out[2]: [True, False]
No, because that's not the way that and operation works in python. First off it doesn't and the list items separately. Secondly the and operator works between two objects and if one of them is False (evaluated as False 1) it returns that and if both are True it returns the second one. Here is an example :
>>> [] and [False]
[]
>>>
>>> [False] and []
[]
>>> [False] and [True]
[True]
x and y : if x is false, then x, else y
If you want to apply the logical operations on all the lists pairs you can use numpy arrays:
>>> import numpy as np
>>> a = np.array([True, False])
>>> b = np.array([True, True])
>>>
>>> np.logical_and(a,b)
array([ True, False], dtype=bool)
>>> np.logical_and(b,a)
array([ True, False], dtype=bool)
1. Here since you are dealing with lists an empty list will be evaluated as False
Related
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
This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 3 years ago.
mytest=[[False]*3]*2
In [46]: mytest
Out[46]: [[False, False, False], [False, False, False]]
In [47]: mytest[0][1]=True
In [48]: mytest
Out[48]: [[False, True, False], [False, True, False]]
On the other hand
mytest=[ [False]*3 for i in range(2)]
In [53]: mytest[0][1]=True
In [54]: mytest
Out[54]: [[False, True, False], [False, False, False]]
On the first when in set [0][1], it sets at two places , but in second it sets correctly .. what is wrong with first assignment.
This is how Python handles objects. In your first example, the list mytest contains two [False, False, False] lists that are stored at the same memory location (i.e., both items in the list are pointing to the same memory location). When you change the one, the other is changed as well because simply they are both pointing to the same list in memory.
In the second example, and when you are using list comprehension the two lists [False, False, False] are two different objects pointing to different memory locations.
Proof
>>> mytest=[[False]*3]*2
>>> id(mytest[0])
4340367304
>>> id(mytest[1])
4340367304
>>> mytest=[ [False]*3 for i in range(2)]
>>> id(mytest[0])
4340436936
>>> id(mytest[1])
4340498512
The difference with the first and second statement is that your first statement will first evaluate [False] * 3 first which gives [False, False, False] and then *2 will create two references of that object ([False, False, False]). In the second example, you are creating a [False, False, False] each time.
This question already has answers here:
Repeating each element of a numpy array 5 times
(2 answers)
Closed 3 years ago.
I have a numpy.ndarray with True/False:
import numpy as np
a = np.array([True, True, False])
I want:
out = np.array([True, True, False, True, True, False, True, True, False])
I tried:
np.repeat(a, 3, axis = 0)
But it duplicates each element, I want to duplicate the all array.
This is the closes I got:
np.array([a for i in range(3)])
However, I want it to stay as 1D.
Edit
It was suggested to be a duplicate of Repeating each element of a numpy array 5 times. However, my question was how to repeat the all array and not each element.
Use np.tile
>>> a = np.array([True, True, False])
>>> np.tile(a, 3)
... array([ True, True, False, True, True, False, True, True, False])
Try:
import numpy as np
a = np.array([True, True, False])
print(np.concatenate([a]*3))
[ True True False True True False True True False]
I have a list of lists which are composed by bools, let's say l = [[False, False], [True, False]], and I need to convert l to a numpy array of arrays of booleans. I converted every sublist into a bool array, and the whole list to numpy array too. My current real list has a size of 121 sublists, and the result of np.any() throws just five results, not the 121 expected. My code is this:
>>> result = np.array([ np.array(extracted[aindices[i]:aindices[i + 1]]) for i in range(len(aux_regions)) ])
>>> np.any(result)
[false, false, false, false, false]
extracted[aindices[i]:aindices[i + 1]] is the sublist which I convert to a bool array. The list generated in the whole line is converted to array too.
In the first example l the expected result is, for every subarray (asuming the list as converted) should be [False, True]
What's is the problem using np.any? or the data types for the converted list are not the right ones?
If you have a list of list of bools, you could skip numpy and use a simple comprehension:
In [1]: l = [[False, False], [True, False]]
In [2]: [any(subl) for subl in l]
Out[2]: [False, True]
If the sublists are all the same length, you can pass the list directly to np.array to get a numpy array of bools:
In [3]: import numpy as np
In [4]: result = np.array(l)
In [5]: result
Out[5]:
array([[False, False],
[ True, False]], dtype=bool)
Then you can use the any method on axis 1 to get the result for each row:
In [6]: result.any(axis=1) # or `np.any(result, axis=1)`
Out[6]: array([False, True], dtype=bool)
If the sublists are not all the same length, then a numpy array might not be the best data structure for this problem.
This part of my answer should be considered a "side bar" to what I wrote above. If the sublists have variable lengths, the list comprehension given above is my recommendation. The following is an alternative that uses an advanced numpy feature. I only suggest it because it looks like you already have the data structures needed to used numpy's reduceat function. It works without having to explicitly form the list of lists.
From reading your code, I infer the following:
extracted is a list of bools. You are splitting this up into sublists.
aindices is a list of integers. Each consecutive pair of integers in aindices specifies a range in extracted that is a sublist.
len(aux_regions) is the number of sublists; I'll call this n. The length of aindices is n+1, and the last value in aindices is the length of extracted.
For example, if the data looks like this:
In [74]: extracted
Out[74]: [False, True, False, False, False, False, True, True, True, True, False, False]
In [75]: aindices
Out[75]: [0, 3, 7, 10, 12]
it means there are four sublists:
In [76]: extracted[0:3]
Out[76]: [False, True, False]
In [77]: extracted[3:7]
Out[77]: [False, False, False, True]
In [78]: extracted[7:10]
Out[78]: [True, True, True]
In [79]: extracted[10:12]
Out[79]: [False, False]
With these data structures, you are set up to use the reduceat feature of numpy. The ufunc in this case is logical_or. You can compute the result with this one line:
In [80]: np.logical_or.reduceat(extracted, aindices[:-1])
Out[80]: array([ True, True, True, False], dtype=bool)
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]