2013-05-10 5 views
1

У меня есть функция, которая возвращает следующий словарюсловарь, который содержит список

abc= {"type":"insecure","id":"1", 
     "name":"peter","s_count":"2", 
     "b_count":"1", "s_1_name":"melisa", 
     "s_1_id":"2","s_2_name":"graham", 
     "s_2_id":"4", "b_1_name":"henrik", 
     "b_1_id": "9"} 

Я хочу, чтобы Ставить словарь следующим образом:

xyz={"type":"insecure","id":"1", 
    "name":"peter", 
     "s" : [{"id" : "2", "name": "melisa"}, 
      {"id" : "4", "name": "graham"}], 
     "b" : [{"id" : "9", "name": "henrik"}]} 

Логика такова: если есть s_count в словаре затем создайте список, содержащий все значения, начинающиеся с s. например, в моем случае создать аа список, которые содержат различные словари с каждым словарем, содержащих s_name и s_id, например, в моем случае есть два словаря в результирующем списке:

"s" : [{"id" : "2", "name": "melisa"},{"id" : "4", "name": "graham"}] 

и сделать то же самое с б а если b_count счет существует.

Может ли кто-нибудь помочь мне с этим?

+2

Может ли быть '' a_count' или c_count 'или это только те два, что вы упомянули? – jamylak

+0

Нет, он будет иметь только s_count и b_count или без значений, начинающихся с префикса s_ или b_. – hjelpmig

+1

Я не согласен с тем, что это слишком локализовано; чтобы возобновить голосование. Основная проблема заключается в том, как эффективно обрабатывать словарные ключи с общим префиксом. –

ответ

4

Я хотел бы использовать вспомогательную функцию:

from itertools import groupby 
from operator import itemgetter 

def extract_keys(mapping, prefix): 
    prefix = '{}_'.format(prefix) 

    # test for the `.._count` key first, if it's not there, bail out early 
    if prefix + 'count' not in mapping: 
     return None 

    # find all matching keys, split out the counter for sorting and grouping 
    keys = [(k, int(k.split('_', 2)[1])) 
     for k in mapping if k.startswith(prefix) and k != prefix + 'count'] 
    keys.sort(key=itemgetter(1)) 

    # group keys on the counter, then generate a dictionary per counter value 
    return [{k[0].split('_', 2)[-1]: mapping[k[0]] for k in group} 
     for c, group in groupby(keys, itemgetter(1))] 

Эта функция извлекает ключи префиксом:

>>> extract_keys(abc, 's') 
[{'id': '2', 'name': 'melisa'}, {'name': 'graham', 'id': '4'}] 
>>> extract_keys(abc, 'b') 
[{'name': 'henrik', 'id': '9'}] 

использование этой функции для создания новых словарей или преобразовать существующие словари на месте:

xyz = {k: v for k, v in abc.iteritems() if not k.startswith('s_') and not k.startswith('b_')} 
s_values = extract_keys(abc, 's') 
if s_values is not None: 
    xyz['s'] = s_values 
b_values = extract_keys(abc, 'b') 
if b_values is not None: 
    xyz['b'] = b_values 

Это преобразует ваш образец abc ввод в:

>>> pprint(xyz) 
{'b': [{'id': '9', 'name': 'henrik'}], 
'id': '1', 
'name': 'peter', 
's': [{'id': '2', 'name': 'melisa'}, {'id': '4', 'name': 'graham'}], 
'type': 'insecure'} 
+0

благодарит за вашу помощь. он решил мою проблему. Я также немного улучшил код, чтобы сделать его более гибким и может обрабатывать все разделенные, но не могущие сообщения, поскольку вопрос был закрыт :('code' # найти все соответствующие ключи, разделить счетчик для сортировки и группировки keys = [ (k, int (k.split ('_', -1) [- 2])) для отображения k, если k.startswith (префикс) и k! = префикс + 'count'] keys.sort (key = itemgetter (1)) # групповые клавиши на счетчике return [{k [0] .split ('_', -1) [- 1]: отображение [k [0]] для k в группе} для c, группа в groupby (ключи, itemgetter (1))] – hjelpmig

0

Я улучшил его немного больше, чтобы он стал более гибким.

def extract_keys(mapping, prefix): 
prefix = "{}_".format(prefix) 

# test for the `.._count` key first, if it's not there, bail out early 
if prefix + "count" not in mapping: 
    return None 

# find all matching keys, split out the counter for sorting and grouping 
keys = [(k, int(k.split("_", -1)[-2])) for k in mapping if k.startswith(prefix) and k != prefix + "count"] 
keys.sort(key=itemgetter(1)) 

# group keys on the counter, then generate a dictionary per counter value 
return [{k[0].split("_", -1)[-1]: mapping[k[0]] for k in group} for c, group in groupby(keys, itemgetter(1))] 

рассмотрите следующий словарь.

abc= {"type":"insecure","id":"1", 
    "name":"peter","s_a_count":"2", 
    "b_count":"1", "s_a_1_name":"melisa", 
    "s_a_1_id":"2","s_a_2_name":"graham", 
    "s_a_2_id":"4", "b_1_name":"henrik", 
    "b_1_id": "9"} 

использование этой функции для создания новых словарей или преобразовать существующие словари на месте:

xyz = {k: v for k, v in abc.iteritems() if not k.startswith('s_a') and not k.startswith('b_')} 
s_values = extract_keys(abc, 's_a') 
if s_values is not None: 
    xyz['s_a'] = s_values 
b_values = extract_keys(abc, 'b') 
if b_values is not None: 
    xyz['b'] = b_values 

и трансформировали выход:

print xyz 

{'b': [{'id': '9', 'name': 'henrik'}], 
'id': '1', 
'name': 'peter', 
's_a': [{'id': '2', 'name': 'melisa'}, {'id': '4', 'name': 'graham'}], 
'type': 'insecure'} 
+0

Комментарии будут рассмотрены – hjelpmig

Смежные вопросы