5

I am preparing new driver for one of our new hardware devices.

One of the option to set it up, is where one byte, has 8 options in it. Every bite turns on or off something else.

So, basically what I need to do is, take 8 zeros or ones and create one byte of them.

What I did is, I have prepares helper function for it:

@staticmethod
def setup2byte(setup_array):
    """Turn setup array (of 8 booleans) into byte"""
    data = ''
    for b in setup_array:
        data += str(int(b))
    return int(data, 2)

Called like this:

    settings = [echo, reply, presenter, presenter_brake, doors_action, header, ticket_sensor, ext_paper_sensor]
    data = self.setup2byte(settings)
    packet = "{0:s}{1:s}{2:d}{3:s}".format(CONF_STX, 'P04', data, ETX)
    self.queue_command.put(packet)

and I wonder if there is easier way how to do it. Some built in function or something like that. Any ideas?

4
  • 1
    bytearray([int(b) for b in list_of_bools]) Commented Nov 30, 2017 at 14:40
  • @JaredSmith That creates 8 bytes. Asker wants it all in one byte (8 bits). Commented Nov 30, 2017 at 14:47
  • @glibdud good catch, fixed it in my answer. Commented Nov 30, 2017 at 14:51
  • Possible duplicate of Bool array to integer Commented Nov 30, 2017 at 16:45

4 Answers 4

2

I think it is neither necessary to create an intermediate string array, a for-loop nor using a slow power function.

The solution can be crunched down to a one liner using sum and map and the binary shift operator.

settings = [False, True, False, True, True, False, False, True]
x = sum(map(lambda x: x[1] << x[0], enumerate(settings)))
print(bin(x))

> 0b10011010

Remark: The first element in the array has the lowest prio, else the settings would need to be reversed.

Sign up to request clarification or add additional context in comments.

Comments

1

I believe you want this:

convert2b = lambda ls: bytes("".join([str(int(b)) for b in ls]), 'utf-8')

Where ls is a list of booleans. Works in python 2.7 and 3.x. Alternative more like your original:

convert2b = lambda ls: int("".join([str(int(b)) for b in ls]), 2)

1 Comment

This works, but basically just does the same thing the asker is already doing, only in a comprehension.
1

that's basically what you are already doing, but shorter:

data = int(''.join(['1' if i else '0' for i in settings]), 2)

But here is the answer you are looking for: Bool array to integer

1 Comment

It basically does't matter if its string of integer or any other type because it is being sent over serial port to HW which reads it as bites. But it has to be one byte, not 8 bytes. That is the point.
0

I think the previous answers created 8 bytes. This solution creates one byte only

settings = [False,True,False,True,True,False,False,True]
# LSB first


integerValue = 0
# init value of your settings
for idx, setting in enumerate(settings):
    integerValue += setting*2**idx


# initialize an empty byte
mybyte = bytearray(b'\x00')
mybyte[0] =integerValue
print (mybyte)

For more example visit this great site: binary python

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.