我有一个嵌套的dict格式:
dict : {
NAME1 :{
FIELDS :{
FIELD1 :{
MAXBIT:2, MINBIT:0},
FIELD2 :{
MAXBIT:4, MINBIT:3},
FIELD3 :{
MAXBIT:7, MINBIT:5}}}
NAME2
....
}
我想编写一个带NAME
和hex
值的函数,并根据hex
返回dict
的二进制分解。
实施例:
对于输入f(NAME1, 0x0f)
(0x0f
是00001111)和上面的dict,输出将是:
NAME1:
FIELD1: 111
FIELD2: 01
FIELD3: 000
二进制字符串由字段组成,每个字段都有以字节为单位的长度。 漂亮的打印并不重要,我只是在寻找pythonic方式来做到这一点。这是我写的:
def f(name1, hex_value):
fields = []
for field, value in dictionary[name1]['FIELDS'].items():
fields.append([value['MINBIT'], value['MAXBIT'], field])
fields.sort()
binary_string = '{0:b}'.format(int(hex_value, 16))
chunks = [bit_pair[1]-bit_pair[0]+1 for bit_pair in fields]
rev_bin_sring = reversed(binary_string)
sliced_fields = [''.join(islice(rev_bin_sring, i)) for i in chunks]
sliced_fields = [string.replace('', '0') for string in sliced_fields]
final_res = [list((field[2], bin_value)) for bin_value, field in zip(sliced_fields, fields)]
但它看起来很丑陋,我相信有更优雅的方式。
答案 0 :(得分:1)
我已将您的dict
重命名为d
,因为dict
是内置的python对象类型,您真的不应该用自己的变量覆盖它们:
d = {
'NAME1' :{
'FIELDS' :{
'FIELD1' :{
'MAXBIT':2, 'MINBIT':0},
'FIELD2' :{
'MAXBIT':4, 'MINBIT':3},
'FIELD3' :{
'MAXBIT':7, 'MINBIT':5}}}}
def f(name, hex_value):
fields = d[name]['FIELDS']
bin_value = bin(hex_value).replace('b','0')[::-1]
new_d = {name:{}}
for field, value in fields.items():
max_b, min_b = value['MAXBIT']+1, value['MINBIT']
bin_value += '0'*(max_b-len(bin_value))
new_d[name][field] = bin_value[min_b:max_b][::-1]
return new_d
首先根据字典name
中的d
参数获取相关字段。然后它使用bin
函数将hex_value
转换为二进制表示(作为字符串)。 bin_value
的前两个字符将为0b
,因此将b
替换为另一个0
并反转字符串(这将允许您稍后使用字符串切片获取您的值)。现在,对于每个MAXBIT
,MINBIT
对,您可以对bin_value
字符串进行切片,然后将其反转(使用[::-1]
)以获得预期的分解。显然,如果bin_value
短于max_b
值,则会失败。为了适应这种情况,您可以在'0'
的末尾添加额外的bin_value
,以便bin_value
长度至少为max_b
个字符。另请注意max_b = value['MAXBIT'] + 1
,因为您希望将字符包含在max_b
的索引中,但只包含python切片,因此您需要添加1
。
>>> f('NAME1',0x0f)
{'NAME1': {'FIELD1': '111', 'FIELD2': '01', 'FIELD3': '000'}}
修改强>
略有不同的替代品,不需要来回反转所有:
def f(name, hex_value):
fields = d[name]['FIELDS']
bin_value = bin(hex_value).replace('b','0')
new_d = {name:{}}
for field, value in fields.items():
max_b, min_b = value['MAXBIT']+1 , value['MINBIT']
new_d[name][field] = bin_value.zfill(max_b)[-max_b:-min_b or None]
return new_d
>>> f('NAME1',0x0f)
{'NAME1': {'FIELD1': '111', 'FIELD2': '01', 'FIELD3': '000'}}
注意:value['MINBIT'] or None
处理value['MINBIT']
为零的情况。