DnRng
DnRng

Reputation: 167

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 ?

Upvotes: 7

Views: 3920

Answers (5)

slider
slider

Reputation: 12990

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).

Upvotes: 3

timgeb
timgeb

Reputation: 78650

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.

Upvotes: 4

Woody1193
Woody1193

Reputation: 7960

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.

Upvotes: 9

Sheldore
Sheldore

Reputation: 39042

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]

Upvotes: 5

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476547

You can do this with 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.

Upvotes: 3

Related Questions