“查询”字典的 Pythonic 方式

Posted

技术标签:

【中文标题】“查询”字典的 Pythonic 方式【英文标题】:A Pythonic way to "query" a dictionary 【发布时间】:2019-01-27 15:23:14 【问题描述】:

我有一个包含书籍数据的嵌套字典:

UID 条件 价格

这是定义:

books = 
    'uid1':
        'price': '100',
        'condition': 'good',
    'uid2':
        'price': '80',
        'condition': 'fair',
    'uid3':
        'price': '150',
        'condition': 'excellent',
    'uid4':
        'price': '70',
        'condition': 'fair',
    'uid5':
        'price': '180',
        'condition': 'excellent',
    'uid6':
        'price': '60',
        'condition': 'fair'
    

我需要获取按条件分组的平均价格。所以,预期的结果是:

'fair': 70, 'good': 100, 'excellent': 165

最 Pythonic 的方法是什么?

【问题讨论】:

【参考方案1】:

使用collections.defaultdict

演示:

from collections import defaultdict

res = defaultdict(list)
for k,v in books.items():
    res[v['condition']].append(int(v['price'])) 

print(k: sum(v)/len(v) for k, v in res.items() )

输出:

'good': 100, 'fair': 70, 'excellent': 165

【讨论】:

哦,defaultdict 搞定了!谢谢!【参考方案2】:

我想使用 Pandas 库来回答这个问题。

import pandas as pd
books = 
    'uid1':
        'price': '100',
        'condition': 'good',
    'uid2':
        'price': '80',
        'condition': 'fair',
    'uid3':
        'price': '150',
        'condition': 'excellent',
    'uid4':
        'price': '70',
        'condition': 'fair',
    'uid5':
        'price': '180',
        'condition': 'excellent',
    'uid6':
        'price': '60',
        'condition': 'fair'
   
data = pd.DataFrame.from_dict(books, orient='index')
data['price'] = data[['price']].apply(pd.to_numeric)
data.groupby(['condition'])['price'].mean()

输出:

condition
excellent    165
fair          70
good         100

【讨论】:

pandas 似乎是最自然的解决方案。每当我看到 R 比 Python 更优雅地解决某种类型的问题的一种(相对罕见的)情况时,通常会有一个 pandas 解决方案潜伏着。 是的,熊猫可能真的很有用。我有更多的字段和潜在的查询这本字典,所以创建和查询数据框听起来很有希望。【参考方案3】:

这是一种方法:

from statistics import mean
result = condition: mean(float(book['price']) for book in books.values() if book['condition'] == condition) for condition in ('fair','good','excellent')

#result = 'fair': 70.0, 'good': 100.0, 'excellent': 165.0

【讨论】:

这假设您已经知道可能的条件列表。如果你不这样做呢? @SembeiNorimaki 然后你必须做一些不那么优雅的事情(如果你想使用直接的字典理解)。这个限制是我支持pandas 答案并很高兴看到它被接受的原因之一。【参考方案4】:

我不明白你为什么需要defaultdict,除了不使用Try Except -

for k, v in books.items():
    try:
        avg[v['condition']].append(int(v['price']))
    except KeyError:
        avg[v['condition']] = [int(v['price'])]
avg = k: sum(v)/len(v) for k, v in avg.items()

【讨论】:

以上是关于“查询”字典的 Pythonic 方式的主要内容,如果未能解决你的问题,请参考以下文章

浅谈python 字典对象的 Pythonic 用法

字典对象的 Pythonic 用法(上篇)

以pythonic方式打印字典中最大值的键[重复]

将 CSV 值读入列表字典的大多数 Pythonic 方式

寻找一种更 Pythonic 的方式将一个充满字典的列表合并为一个?

如何使用映射或过滤器而不是列表推导过滤特定值的嵌套字典(pythonic 方式)?