【问题标题】:nested dictionary generation based on values from other dictionaries基于来自其他字典的值的嵌套字典生成
【发布时间】:2016-07-04 17:27:12
【问题描述】:

我有两个输入数据集,一个是列表 (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 方式?

【问题讨论】:

  • list1 不是很pythonic。它基本上是一个键:值对列表(您认为应该放在字典中)。您想要一种重新设计数据结构的 Python 方式,还是按原样迭代它们的 Python 方式?
  • 嗨,肯尼,感谢您的评论....实际上,list1 是弹性搜索聚合查询之一的结果,所以我只是在阅读它。顺便说一句,我们可以修改以适应要求...:)

标签: python dictionary


【解决方案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}}

【讨论】:

  • 我认为你应该得到 total_count by sum
  • 问题作者希望通过与先前计数的比较而不是总和来获得它。请参阅问题中给出的预期结果。 “百分比”对他们来说可能只是不好的术语。我相信 total_count 值是任意的,因为它被注释为“任何整数值”,并且列表中的计数加起来是 8,而不是 10。
  • 重读,我不知道应该是多少百分比。没关系。 :)
  • 我想知道是不是应该按键排序(就像你所做的那样),还是使用列表的排序,恰好是相同的顺序,可能是偶然的。
  • @KennyOstrom 这是一个很好的观点,我们需要 OP 来澄清这一点。键是字符串而不是整数这一事实使得它们是否应该传达顺序变得更加不清楚。
【解决方案2】:
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

【讨论】:

    猜你喜欢
    • 2018-01-19
    • 2018-03-27
    • 1970-01-01
    • 2019-01-15
    • 2022-06-13
    • 1970-01-01
    • 2019-12-04
    • 2023-03-15
    • 2015-09-11
    相关资源
    最近更新 更多