python字符串变量长度与嵌套dict分裂

时间:2016-11-14 14:31:28

标签: python

我有一个嵌套的dict格式:

dict : {
    NAME1 :{
            FIELDS :{
                FIELD1 :{
                    MAXBIT:2, MINBIT:0},
                FIELD2 :{
                    MAXBIT:4, MINBIT:3},
                FIELD3 :{
                    MAXBIT:7, MINBIT:5}}}
    NAME2
    ....
    }

我想编写一个带NAMEhex值的函数,并根据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)]

但它看起来很丑陋,我相信有更优雅的方式。

1 个答案:

答案 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并反转字符串(这将允许您稍后使用字符串切片获取您的值)。现在,对于每个MAXBITMINBIT对,您可以对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']为零的情况。