-6

I have a list of values

a = [88,  24, 128, 3] 

Now I have to get these values in binary as a list such as

[0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1] 

and final output as below which gives the position of 1s from the above binary list in hex value

[0x2, 0x4, 0x5, 0xc, 0xd, 0x11, 0x1f, 0x20]

My attempt: shall give the binary list

[((b>>i)&1)for b in a for i in range(7,-1,-1)]

Now I didn't know how to get the final output, but the code has be to in the same in-line code.

final output shall be a list which contains the position of 1s from the binary list.

I need in it one liner code because I use this code in eval function

fastlearner
  • 105
  • 1
  • 8
  • I have this in-line code in a string where inbuilt hex may affect it and also I couldnt get the final output even if a use built-in hex – fastlearner Aug 07 '14 at 13:32
  • 1
    So you want to expand an integer to an 8-bit binary number, then... represent each 8-bit number as two hexadecimals, four bits each? Is that right? Then how does `0101` (`5`) get to `0x2` (`2`)? And why you you ever get `0x20` from 4 bits? If not, what *are* you doing? Could you describe the process you're trying to implement? – jonrsharpe Aug 07 '14 at 13:32
  • 1
    Can you explain how you got from the "binary list" to the output? If I took "the hex value" of the binary list, I'd get `0x58188003`, not an eight element list. – Kevin Aug 07 '14 at 13:33
  • 1
    Here I want a kind of mapping i.e. each 1s position in the binary array shall have a hex value in final output. so 0101(5) has 1 in position 2 and another 1 in position 4. so the final output has [0x2 and 0x4] in it – fastlearner Aug 07 '14 at 13:38
  • Oh, I see. So you treat the whole list as a backwards decimal number, then the output is the hex locations of the `1`s in the list, starting from `1`? In that case, why on earth would you want that? And why would you try to do it in a single line? – jonrsharpe Aug 07 '14 at 13:43
  • @jonrsharpe this is a kind of mapping I have to do. the initial list is mapped to the final output. and I need this in single line to use it with `èval`. – fastlearner Aug 07 '14 at 13:51
  • @Vinoth You don't really need to make something one line to call eval, you may write a function and call it in eval. However, you may try to eliminate eval altogether, since I suspect you don't really need it. –  Aug 07 '14 at 13:52
  • To paraphrase Jamie Zawinski; if you've "solved a problem" with `eval`, you've now got two problems. [`eval` is evil](http://stackoverflow.com/a/1832957/3001761)! – jonrsharpe Aug 07 '14 at 13:52
  • @Jean-ClaudeArbaut ya, I know. but i am not supposed to change the `èval`part. so I need it in single line to have a kind of configuration – fastlearner Aug 07 '14 at 13:57
  • This would be a good reference for many. could anybody reopen the question ? – fastlearner Nov 13 '14 at 13:30

1 Answers1

0

First the final answer, which is really a one-liner. Some explanations follow

a = [88, 24, 128, 3]
[i + 1 for i, x in enumerate("".join(bin(n + 256)[3:] for n in a)) if x == "1"]

This yields

[2, 4, 5, 12, 13, 17, 31, 32]

First transformation:

def dec2bin(a):
    return [int(x) for x in "".join(bin(n + 256)[3:] for n in a)]

On your example

>>> dec2bin([88, 24, 128, 3])
[0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1]

Then to get positions

def positions(a):
    return [i for i in range(len(a)) if a[i] == 1]

The final output

>>> positions(dec2bin([88, 24, 128, 3]))
[1, 3, 4, 11, 12, 16, 30, 31]

Notice the values are off by 1, since Python arrays start at 0. To get your values, simply add 1 to the output values:

def positions(a):
    return [i + 1 for i in range(len(a)) if a[i] == 1]

If you really need them in hex (they will be strings, not numbers, since numbers have no intrinsic base):

>>> list(map(hex, _))
['0x1', '0x3', '0x4', '0xb', '0xc', '0x10', '0x1e', '0x1f']

The whole thing in one line

>>> v = [88, 24, 128, 3]
>>> (lambda a: [i + 1 for i in range(len(a)) if a[i] == 1])([int(x) for x in "".join(bin(n + 256)[3:] for n in v)])
[2, 4, 5, 12, 13, 17, 31, 32]

The lambda is not necessary, you can write this instead, using enumerate. And you can make the line shorter by removing the "int(x)" step:

>>> v = [88, 24, 128, 3]
>>> [i + 1 for i, x in enumerate("".join(bin(n + 256)[3:] for n in v)) if x == "1"]
[2, 4, 5, 12, 13, 17, 31, 32]

Notice the argument of enumerate is a generator, not a list. Same remark for the argument of join.