Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python/Numpy: Convert list of bools to unsigned int

  1. What is the fastest (or most "Pythonic") way to convert

    x = [False, False, True, True]
    

    into 12? (If there is such a way.)

  2. What if x were instead a numpy.array of bools? Is there a special command for that?

I have a large m-by-n array of booleans, where each n-element row represents a single low-dimensional hash of a high-dimensional feature vector. (In the example above, n = 4.) I would like to know the answer in order to compress my data as much as possible. Thank you.


Edit: Thank you for the responses! Using the following test code,

t = 0
for iter in range(500):
    B = scipy.signbit(scipy.randn(1000,20))
    for b in B:
        t0 = time.clock()
        # test code here
        t1 = time.clock()
        t += (t1-t0)
print t

...here were the runtimes on my Thinkpad laptop:

  • My answer: 4.26 sec
  • Sven Marnach 1: 7.88
  • Emil H: 8.51
  • Sven Marnach 2: 8.72
  • delnan: 10.14
  • liori: 53.49

Of course, I welcome any independent tests that may confirm or refute my data!


Edit: In my answer below, changing int(j) to simply j still works, but runs six times as slow! Then perhaps the other answers would become faster if the bool was casted using int. But I'm too lazy to test everything again.


Edit: liori posted results of independent tests here.

like image 692
Steve Tjoa Avatar asked Oct 31 '10 23:10

Steve Tjoa


1 Answers

Taking various ideas from various other answers, here's another way to do it:

sum(1<<i for i, b in enumerate(x) if b)

It is quite fast in my tests - right up with the numpy method for large number of bits even though it overflows like crazy. I used liori's testing module for testing. Steve's method, with the change I suggested, is just barely faster. However, if a lot of these sorts of conversions need to be done at a time (and with not too many bits), I'm betting that numpy will be faster.

like image 150
Justin Peel Avatar answered Oct 01 '22 23:10

Justin Peel