基于其他词典值的嵌套字典生成

时间:2016-07-04 17:27:12

标签: python dictionary

我有两个输入数据集,一个是list(list1),其中包含带键和计数值的字典列表,

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”:{“count”:“”,“percent”:“”}}其中count是根据list1中相应字典的键值计算的。例如,对于key == 1,我们得到count == 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}}

我能够通过正常循环字典列表获得所需的响应,然后将if / else条件检查并生成结果,但我不会发现它非常pythonic。任何人都可以建议实现同样的最佳/ pythonic方法是什么?

2 个答案:

答案 0 :(得分:1)

这应该可以,通过将list1转换为正确的字典,并将dict1排序到列表中。 (因此,你应该采用与本应该开始的方式相反的方式)。然后它创建一个可用于生成字典的生成器。

这也假设dict1中的每个键也在list1中找到。请注意,如果任何计数为零,您将获得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}}

答案 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