2016-07-04 2 views
0

У меня есть два входных наборов данных один является список (песни1), содержащий список словарей с ключами и подсчета значений,вложенного словаря генерации на основе значений из других словарей

list1 = [{u'key': u'1', u'count': 2}, {u'key': u'2', u'count': 1}, {u'key': u'3', u'count': 5}] 

и другой является словарь (dict1) с номерами (строка) в качестве ключа и строки состояния в качестве значений.

dict1 = {'1': "status1", '2': "status2", '3': "status3"} 

Мне нужно создать словарь что-то вроде этого { «status_string»: { «подсчет»: «», «процент»: «»}}, где отсчет рассчитывается на основе значения ключа из соответствующего Dict в списке1. например, для ключа == 1 мы получаем счет == 2. И процент рассчитывается на основе предыдущих значений счета состояния, начиная с total_count, см. желаемый результат ниже для процентов.

Желаемая выход

result = { 
"status1": { 
    "count": { 
     "value_from_list1_where_key = 1" 
    }, 
    "percent": { 
     "(last_calculated_count/total_count)" 
    } 
}, 
"status2": { 
    "count": { 
     "value_from_list1_where_key = 2" 
    }, 
    "percent": { 
     "(last_calculated_count/status1_count)" 
    } 
}, 
"status3": { 
    "count": { 
     "value_from_a_list_where_key = 3" 
    }, 
    "percent": { 
     "(last_calculated_count/status2_count)" 
    } 
} 

}

Пример выше образца:

list1 = [{u'key': u'1', u'count': 2}, {u'key': u'2', u'count': 1}, {u'key': u'3', u'count': 5}] 

dict1 = {'1': "status1", '2': "status2", '3': "status3"} 

total_count = 10 #any integer value 

result = {"status1": {"count": 2, "percent": 2/10}, 
     "status2": {"count": 1, "percent": 1/2}, 
     "status3": {"count": 5, "percent": 5/1}} 

я в состоянии, чтобы получить желаемый ответ, нормальный цикл по списку словарей, а затем положить, если/else, чтобы проверить и сгенерировать результат, но я не найду его очень pythonic. Может ли кто-нибудь предложить, какой лучший/питонический способ достичь того же?

+0

list1 не очень pythonic. Это в основном список пар ключ: значение (который, по вашему мнению, должен идти в dict). Вы хотите, чтобы pythonic перепроектировал структуры данных, или питоновский способ повторить их AS-IS? –

+0

Привет, Кенни, спасибо за комментарий .... Фактически список1 является результатом одного из запросов агрегирования на поиск эластичных изображений, поэтому я просто его читаю. BTW мы можем изменить в соответствии с требованием ... :) –

ответ

1

Это должно сработать путем преобразования списка1 в соответствующий словарь и сортировки dict1 в список. (Следовательно, у вас было противоположное тому, как должно было начинаться). Затем он создает генератор, который может использоваться для создания словаря.

Это также предполагает, что каждый ключ в dict1 также находится в списке1. Обратите внимание, что вы получите ZeroDivisionError, если любой из отсчетов равен нулю (кроме последнего, но вам просто повезло). Я не знаю, чего вы хотите, как ожидаемого результата, если это произойдет, и вам нужно будет уточнить.

from __future__ import division # without this you will get 0 for most of your percents 

L = [{u'key': u'1', u'count': 2}, {u'key': u'2', u'count': 1}, {u'key': u'3', u'count': 5}] 
D = {'1': "status1", '2': "status2", '3': "status3"} 

def gen_result(list1, dict1, total_count): 
    counts = {k['key']: k['count'] for k in list1} # makes list1 accessible by key value 
    statuses = sorted(dict1.items()) # sorts the statuses in ascending order 
    for key, status in statuses: 
     count = counts[key] # accesses the count value from list1 (via counts dict) 
     yield status, {'count': count, 'percent': count/total_count} # yields a key, value pair for the dictionary result 
     total_count = count # sets total_count equal to the current count value, so that it can be compared to the next count value on the next iteration. 

print(dict(gen_result(L, D, 10))) # materializes dictionary 

#>>> {'status1': {'count': 2, 'percent': 0.2}, 
#  'status3': {'count': 5, 'percent': 5.0}, 
#  'status2': {'count': 1, 'percent': 0.5}} 
+0

Я думаю, что вы должны получить total_count суммой –

+0

Автор вопроса хочет его по сравнению с предыдущим счетом, а не суммой. Посмотрите ожидаемый результат, указанный в вопросе. «Процент» - это, вероятно, просто плохая терминология с их стороны. Я считаю, что значение total_count является произвольным, поскольку оно прокомментировано как «любое целочисленное значение», а количество в списке составляет до 8, а не 10. –

+1

перечитывание, я не знаю, какой процент должен быть. Неважно. :) –

0
from operator import itemgetter as get 

def convert(key_counts, key_to_status, total): 
    counts = map(get('count'), key_counts) 
    keys = map(get('key'), key_counts) 
    status_counts = zip(map(key_to_status.get, keys), counts) 
    totals = [total] + counts[:-1] 
    return { status: {'count': count, 'percent': count/total} 
       for (status, count), total in zip(status_counts, totals) } 

if __name__ == '__main__': 
    list1 = [{u'key': u'1', u'count': 2}, {u'key': u'2', u'count': 1}, {u'key': u'3', u'count': 5}] 

    dict1 = {'1': "status1", '2': "status2", '3': "status3"} 

    total_count = 10 #any integer value 

    print(convert(list1, dict1, total_count)) 

# returns {'status1': {'count': 2, 'percent': 0}, 
#   'status3': {'count': 5, 'percent': 5}, 
#   'status2': {'count': 1, 'percent': 0}} 

Если вы хотите плавать разделение, вы должны заменить count/total с float(count)/total.

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