4

I have a list of True and False answers like this:

[True, True, True, False, False, True, False, False]
[True, True, False, False, True, False, False, True]
[True, False, False, True, False, False, True, True]
[False, False, True, False, False, True, True, True]
[False, True, False, False, True, True, True, False]
[True, False, False, True, True, True, False, False]
[False, False, True, True, True, False, False, True]
[False, True, True, True, False, False, True, False]

I want to give True a value of 1 and False a value of 0 and then convert that overall value to hexadecimal. How would I go about doing that? Could I look at each value in turn in the list and if it equals 'True' change that value to a 1 and if its 'False' change the value to a 0 or would there be an easier way to change the entire list straight to hex?

EDIT: Here's the full code on Pastebin: http://pastebin.com/1839NKCx

Thanks

Tom Pitts
  • 590
  • 7
  • 25

6 Answers6

7
lists = [
    [True, True, True, False, False, True, False, False],
    [True, True, False, False, True, False, False, True],
    [True, False, False, True, False, False, True, True],
    [False, False, True, False, False, True, True, True],
    [False, True, False, False, True, True, True, False],
    [True, False, False, True, True, True, False, False],
    [False, False, True, True, True, False, False, True],
    [False, True, True, True, False, False, True, False],
]

for l in lists:
    zero_one = map(int, l)  # convert True to 1, False to 0  using `int`
    n = int(''.join(map(str, zero_one)), 2)  # numbers to strings, join them
                                             # convert to number (base 2)
    print('{:02x}'.format(n))  # format them as hex string using `str.format`

output:

e4
c9
93
27
4e
9c
39
72
falsetru
  • 357,413
  • 63
  • 732
  • 636
  • @JohnZwinck, I think you overwrote `map` with a dictionary object. I checked this code both in Python 2.7 and Python 3.4. – falsetru Aug 30 '14 at 14:26
  • "TypeError: argument 2 to map() must support iteration" Confused on what that exactly means, Google hasn't helped. – Tom Pitts Aug 30 '14 at 14:39
  • @TomPitts, Could you show your code and the full traceback? (by putting somewhere like pastebin) – falsetru Aug 30 '14 at 14:40
  • @TomPitts, I think you passed non-sequence (or non-iterable) as the second argument. for example `int`: `map(str, 1)`. You should pass iterable: `map(str, [1])` – falsetru Aug 30 '14 at 14:43
  • @TomPitts, There's no call to `map`. Is the error message really come by running the source code? – falsetru Aug 30 '14 at 14:55
  • @TomPitts, The code is overwrite `foo`, instead of appending differences to the `foo`. Try this: http://pastebin.com/dq7psYy7 – falsetru Aug 30 '14 at 15:03
  • Wow nice job! Thank you very much! How would I make that just one hex string rather than a hex value on each line? You've been amazing help! – Tom Pitts Aug 30 '14 at 15:16
  • @TomPitts, append strings instead of printing, and print it later. Most simply way would be concatenating strings: (`str += str`) http://pastebin.com/13wZMz8V – falsetru Aug 30 '14 at 15:20
1

No need for a two steps process if you use reduce (assuming MSB is at left as usual):

b = [True, True, True, False, False, True, False, False]
val = reduce(lambda byte, bit: byte*2 + bit, b, 0)

print val
print hex(val)

Displaying:

228
0xe4
Sylvain Leroux
  • 50,096
  • 7
  • 103
  • 125
  • 2
    You can just use `bit` instead of `(1 if bit else 0)` because `bool` is subclass of `int` and can be used in arithmetic oepration. If you want to be explicit, use `int(bit)`. – falsetru Aug 30 '14 at 14:31
1

If you want to combine a series of boolean values into one value (as a bitfield), you could do something like this:

x = [True, False, True, False, True, False ]
v = sum(a<<i for i,a in enumerate(x))
print hex(v)
khelwood
  • 55,782
  • 14
  • 81
  • 108
  • That's worked a treat, but its now doing this: [True, True, True, False, False, True, False, False] 0x27 [True, True, False, False, True, False, False, True] 0x93 [True, False, False, True, False, False, True, True] 0xc9 [False, False, True, False, False, True, True, True] 0xe4 [False, True, False, False, True, True, True, False] 0x72 How would I gather up all those Hex values into one string? – Tom Pitts Aug 30 '14 at 14:32
0

This should do it:

def bool_list_to_hex(list):
  n = 0
  for bool in list:
    n *= 2
    n += int(bool)
  return hex(n)
olleicua
  • 2,039
  • 2
  • 21
  • 33
0

One-liner:

>>> lists = [
[True, True, True, False, False, True, False, False],
[True, True, False, False, True, False, False, True],
[True, False, False, True, False, False, True, True],
[False, False, True, False, False, True, True, True],
[False, True, False, False, True, True, True, False],
[True, False, False, True, True, True, False, False],
[False, False, True, True, True, False, False, True],
[False, True, True, True, False, False, True, False]]
>>> ''.join(hex(int(''.join('1' if boolValue else '0' for boolValue in byteOfBools),2))[2:] for byteOfBools in lists)
'e4c993274e9c3972'

Inner join produces a string of eight zeros and ones.

int(foo,2) turns the string into a number interpreting it as binary.

hex turns it to hex format.

[2:] removes the leading '0x' from the standard hex format

outer join does this to all sublists and, well, joins the results.

Emilio M Bumachar
  • 2,532
  • 3
  • 26
  • 30
  • `'%x' % int(''.join('01'[b] for b in sum(lists, [])), 2)` – falsetru Aug 30 '14 at 14:46
  • watch out, this will give you incorrect results if one of the 8 binary array values is less than 10. this is because hex() returns a single character for those values, as in hex(1) == '1' instead of '01'. it is better indeed to use '%x' as @falsetru recommends -- actually, you need to use '%02x' to avoid this same issue as the answer above – Greg Sadetsky Feb 12 '18 at 20:12
0

All above methods do not work if list of bits exceeds 64. It could also be discussed whether it is efficient to transtype boolean several times especially string before conversion to hexa.

Here is a proposal, with MSB on th left of bitlist :

from collections import deque

# (lazy) Padd False on MSB side so that bitlist length is multiple of 4.
# Padded length can be zero
msb_padlen = (-len(bitlist))%4
bitlist = deque(bitlist)
bitlist.extendleft([False]*msb_padlen)

# (lazy) Re-pack list of bits into list of 4-bit tuples
pack4s = zip(* [iter(bitlist)]*4)

# Convert each 4-uple into hex digit
hexstring = [hex(sum(a<<i for i,a in enumerate(reversed(pack4))))[-1] for pack4 in pack4s ]

# Compact list of hex digits into a string
hexstring = '0x'+''.join(hexstring)

The 4-bit tuple pack4 is (msb,...,lsb) => it has to be reversed while calculating corresponding integer.

Alternative :

hexstring = [hex(sum(a<<3-i for i,a in enumerate(pack4)))[-1] for pack4 in pack4s ]
Yoghourt
  • 1
  • 2