12

I have a binary array, and I would like to convert it into a list of integers, where each int is a row of the array.

For example:

from numpy import *
a = array([[1, 1, 0, 0], [0, 1, 0, 0], [0, 1, 1, 1], [1, 1, 1, 1]])

I would like to convert a to [12, 4, 7, 15].

Eli Sander
  • 1,228
  • 1
  • 13
  • 29

5 Answers5

33

@SteveTjoa's answer is fine, but for kicks, here's a numpy one-liner:

In [19]: a
Out[19]: 
array([[1, 1, 0, 0],
       [0, 1, 0, 0],
       [0, 1, 1, 1],
       [1, 1, 1, 1]])

In [20]: a.dot(1 << arange(a.shape[-1] - 1, -1, -1))
Out[20]: array([12,  4,  7, 15])

(arange is numpy.arange.)

If the bits are in the opposite order, change the order of the values produced by arange:

In [25]: a.dot(1 << arange(a.shape[-1]))
Out[25]: array([ 3,  2, 14, 15])
Warren Weckesser
  • 110,654
  • 19
  • 194
  • 214
  • what if the size of the array is very large? (like greater than 64). In that case '1 << arange(a.shape[-1] - 1, -1, -1)' returns negative values. So can we work around that? – appsdownload Sep 12 '18 at 17:29
  • In that case, the integers exceed the limits that can be represented with the standard numpy data types. How to handle that depends on how the result will be used. These comments aren't the place to discuss that. If you have such a need, and need help with your implementation, you could ask a new question. If you do, be sure to explain why it is not a duplicate of this question. – Warren Weckesser Sep 12 '18 at 17:42
8

I once asked a similar question here. Here was my answer, adapted for your question:

def bool2int(x):
    y = 0
    for i,j in enumerate(x):
        y += j<<i
    return y

In [20]: a
Out[20]: 
array([[1, 1, 0, 0],
       [0, 1, 0, 0],
       [0, 1, 1, 1],
       [1, 1, 1, 1]])

In [21]: [bool2int(x[::-1]) for x in a]
Out[21]: [12, 4, 7, 15]
Community
  • 1
  • 1
Steve Tjoa
  • 59,122
  • 18
  • 90
  • 101
  • 1
    This is perfect! I only searched for questions about binary, not booleans, so I didn't see your earlier question. Thanks for your help. – Eli Sander Mar 19 '13 at 16:58
2

You could also do this within numpy directly:

from numpy import *
a = array([[1, 1, 0, 0], [0, 1, 0, 0], [0, 1, 1, 1], [1, 1, 1, 1]])

b2i = 2**arange(a.shape[0]-1, -1, -1)

result = (a*b2i).sum(axis=1)  #[12  4  7 15]
tom10
  • 67,082
  • 10
  • 127
  • 137
2

If you like working directly with bitwise math, this one should work pretty well.

def bits2int(a, axis=-1):
    return np.right_shift(np.packbits(a, axis=axis), 8 - a.shape[axis]).squeeze()

bits2int(a)
Out: array([12,  4,  7, 15], dtype=uint8)
Daniel F
  • 13,620
  • 2
  • 29
  • 55
0

Another one:

def row_bits2int(arr):
    n = arr.shape[1]  # number of columns

    # shift the bits of the first column to the left by n - 1
    a = arr[:, 0] << n - 1  

    for j in range(1, n):
        # "overlay" with the shifted bits of the next column
        a |= arr[:, j] << n - 1 - j  
    return a
Andreas K.
  • 9,282
  • 3
  • 40
  • 45