用于某些字典操作的Pythonic解决方案

时间:2015-09-17 10:01:27

标签: python json

我有以下字典:

{'dev1': {'beacons': [{'mac_address': '11:22:33:44:55:66', 'rssi': 5},
                      {'mac_address': 'ab:bc:cd:de:ef', 'rssi': 22}],
          'mac_addr': '43:34:23:66:11:aa'},
 'dev2': {'beacons': [{'mac_address': '11:22:33:44:55:66', 'rssi': 15},
                      {'mac_address': 'ab:bc:cd:de:ef', 'rssi': 33}],
          'mac_addr': '32:32:54:12:dd:ff'},
 'dev3': {'beacons': [{'mac_address': '11:22:33:44:55:66', 'rssi': 30},
                      {'mac_address': 'ab:bc:cd:de:ef', 'rssi': 44}],
          'mac_addr': '43:fs:43:ha:bb:11'}}

我想把它变成以下

{'mac_address': '11:22:33:44:55:66', 'rssi': [5, 15, 30]}

对于每个唯一的mac_addr组,所有其他属性在一起。我想将它从dev-1/2/3视角转变为信标视角。还有其他键可用,所以它应该使用多个键。

手动可行,有些用于循环等等。我只是想知道是否有一种pythonic方式?

到目前为止,我尝试使用groupby和chain而没有任何运气。

2 个答案:

答案 0 :(得分:0)

def list_dict(seq, seq_factory=None):    
    """
       construct a dictionary key -> list(values).

       Works much like dict(seq) but allows repetition of keys
    """
    d = collections.defaultdict(seq_factory or list)    
    for k, v in seq:    
        d[k].append(v)    
    return d

list_dict(
   (b['mac_address'], b['rssi']) for d in data.values() for b in d['beacons']
)

但我真的怀疑嵌套列表理解是更具可读性

答案 1 :(得分:0)

您可以使用itertools和list comprehensions

import itertools
data = {'dev1': {'beacons': 
                   [{'mac_address': '11:22:33:44:55:66', 'rssi': 5},
                    {'mac_address': 'ab:bc:cd:de:ef', 'rssi': 22}],
                'mac_addr': '43:34:23:66:11:aa'},
        'dev2': {'beacons': 
                   [{'mac_address': '11:22:33:44:55:66', 'rssi': 15},
                    {'mac_address': 'ab:bc:cd:de:ef', 'rssi': 33}],
                'mac_addr': '32:32:54:12:dd:ff'},
        'dev3': {'beacons': 
                   [{'mac_address': '11:22:33:44:55:66', 'rssi': 30},
                   {'mac_address': 'ab:bc:cd:de:ef', 'rssi': 44}],
                'mac_addr': '43:fs:43:ha:bb:11'}}

# flatten the list into
#  [{'rssi':... , 'mac_address': ...},
#   {'rssi': ..., ... ]
flattened = [datum for datum in dev['beacons'] 
                   for dev in data.values()]

result = [ 
           {'rssi': rssi, 
            'mac_address' : [record['mac_address'] for record in records] }

           for rssi, records in itertools.groupby(
             flattened, lambda datum: datum['rssi'])
         ]