Python multidimensional arrays are the most efficient way to count the number of non-zero entries

Hello Saturday night

I communicate in python, and I really like it.

Suppose I have a python array:

x = [1, 0, 0, 1, 3] 

What is the fastest way to count all nonzero elements in a list (ans: 3)? In addition, I would like to do this without for loops, if possible - the most succinct and eloquent, perhaps something conceptually similar to

 [counter += 1 for y in x if y > 0] 

Now - my real problem is that I have a multidimensional array, and I really want to avoid the following:

 for p in range(BINS): for q in range(BINS): for r in range(BINS): if (mat3D[p][q][r] > 0): some_feature_set_count += 1 

From the little python I saw, my gut feeling is that there is a really clean syntax (and efficient) way to do it.

Ideas, anyone?

+6
python arrays multidimensional-array
source share
7 answers

For the one-dimensional case:

 sum(1 for i in x if i) 

In the multidimensional case, you can either attach:

 sum(sum(1 for i in row if i) for row in rows) 

or do it all inside one construct:

 sum(1 for row in rows for i in row if i) 
+12
source share

If you use numpy , as suggested by the fact that you are using multidimensional arrays in Python, the following is similar to @Marcelo's answer, but a little cleaner:

 >>> a = numpy.array([[1,2,3,0],[0,4,2,0]]) >>> sum(1 for i in a.flat if i) 5 >>> 
+3
source share

If you go with numpy and your 3D array is a numpy array, this single line file will do the trick:

 numpy.where(your_array_name != 0, 1, 0).sum() 

Example:

 In [23]: import numpy In [24]: a = numpy.array([ [[0, 1, 2], [0, 0, 7], [9, 2, 0]], [[0, 0, 0], [1, 4, 6], [9, 0, 3]], [[1, 3, 2], [3, 4, 0], [1, 7, 9]] ]) In [25]: numpy.where(a != 0, 1, 0).sum() Out[25]: 18 
+2
source share

Although perhaps not brief, it is my choice how to solve this problem, which works for any dimension:

 def sum(li): s = 0 for l in li: if isinstance(l, list): s += sum(l) elif l: s += 1 return s 
0
source share
 def zeros(n): return len(filter(lambda x:type(x)==int and x!=0,n))+sum(map(zeros,filter(lambda x:type(x)==list,n))) 

This cannot be said if this is the fastest way, but it is recursive and works with N dimensional lists.

 zeros([1,2,3,4,0,[1,2,3,0,[1,2,3,0,0,0]]]) => 10 
0
source share

I would slightly change Marcelo's answer to the following:

 len([x for x in my_list if x != 0]) 

The sum () above me tricked me for a second, since I thought that he gets the total value instead of counting until I see how 1 soars in the beginning. I would rather be explicit with len ().

0
source share

Using a chain to search for arrays:

 from itertools import chain BINS = [[[2,2,2],[0,0,0],[1,2,0]], [[1,0,0],[0,0,2],[1,2,0]], [[0,0,0],[1,1,1],[1,3,0]]] sum(1 for c in chain.from_iterable(chain.from_iterable(BINS)) if c > 0) 14 

I have not performed any performance checks. But he does not use significant memory. Note that it uses a generator expression, not a list comprehension. Adding the syntax [list comprehension] will create an array that will be summed instead of feeding one number at a time to sum.

0
source share

All Articles