Python itertools.groupby 具有多个值的字典
Python itertools.groupby with dictionaries with multiple values
我正在尝试使用 Python itertools.groupby 函数来更改此列表:
items = [
{'price': 5.0, 'name': 'Strawberries'},
{'price': 5.0, 'name': 'Strawberries'},
{'price': 5.0, 'name': 'Strawberries'},
{'price': 11.23, 'name': 'Coffee'},
{'price': 11.23, 'name': 'Coffee'},
{'price': 3.11, 'name': 'Green Tea'}
]
进入这个:
{
'Strawberries': {'price': 5.0, 'quantity': 3},
'Coffee': {'price': 11.23, 'quantity': 2},
'Green Tea': {'price': 3.11, 'quantity': 1}
}
我都试过了:
grouped = {
name: {
'price': list(article)[0]['price'],
'quantity': len(list(article))
} for name, article in groupby(items, key=lambda x: x['name'])
}
和:
grouped = {
name: {
'quantity': list(article),
'price': list(article)[0]['price']
} for name, article in groupby(items, key=lambda x: x['name'])
}
结果如下:
{
'Strawberries': {'price': 5.0, 'quantity': []},
'Coffee': {'price': 11.23, 'quantity': []},
'Green Tea': {'price': 3.11, 'quantity': []}
}
IndexError: list index out of range
我不确定为什么我只能访问我尝试创建的子字典中的一个值的文章。
如有任何建议,我们将不胜感激。
谢谢!
在我看来,这不是 groupby
的最佳用例。在 items
.
上循环构建 (default)dict
更容易
from collections import defaultdict
result = defaultdict(lambda: {'price': None, 'quantity': 0})
for item in items:
subdict = result[item['name']]
subdict['quantity'] += 1
subdict['price'] = item['price']
输出:
>>> result
defaultdict(<function __main__.<lambda>()>,
{'Strawberries': {'price': 5.0, 'quantity': 3},
'Coffee': {'price': 11.23, 'quantity': 2},
'Green Tea': {'price': 3.11, 'quantity': 1}})
(如果价格被商品的最后一次看到的价格覆盖。如果您不希望具有相同名称的商品的价格不明确,这是可以的。)
编辑:没有 defaultdict
result = {}
for item in items:
result.setdefault(item['name'], {'price': item['price'], 'quantity': 0})['quantity'] += 1
您得到空白列表或索引错误的原因是因为您的 article
对象是一个迭代器,它在第一次调用 list(article)
时被完全消耗。
当你第一次拿到价格时,价格是正确的,但数量是空的,因为你已经消费了article
。相比之下,当您先获取数量然后获取第一个项目的价格时,第二次调用 list(article)
会生成一个空列表,您尝试对其进行索引但不能,因为没有项目。
这是 groupby
的解决方案,您可以在其中保存 list(article)
并将其用于价格和数量。
grouped = {}
for name, article in groupby(items, key=lambda itm: itm["name"]):
products = list(article)
grouped[name] = {
"price": products[0]["price"],
"quantity": len(products),
}
编辑:如评论中所述,这假定您的 items
列表按照您想要的顺序排列。通常您会希望以有意义的方式对传递给 groupby()
的可迭代对象进行排序。但也许您只是想将连续的项目组合在一起,即使相同的项目出现在列表的后面。
我正在尝试使用 Python itertools.groupby 函数来更改此列表:
items = [
{'price': 5.0, 'name': 'Strawberries'},
{'price': 5.0, 'name': 'Strawberries'},
{'price': 5.0, 'name': 'Strawberries'},
{'price': 11.23, 'name': 'Coffee'},
{'price': 11.23, 'name': 'Coffee'},
{'price': 3.11, 'name': 'Green Tea'}
]
进入这个:
{
'Strawberries': {'price': 5.0, 'quantity': 3},
'Coffee': {'price': 11.23, 'quantity': 2},
'Green Tea': {'price': 3.11, 'quantity': 1}
}
我都试过了:
grouped = {
name: {
'price': list(article)[0]['price'],
'quantity': len(list(article))
} for name, article in groupby(items, key=lambda x: x['name'])
}
和:
grouped = {
name: {
'quantity': list(article),
'price': list(article)[0]['price']
} for name, article in groupby(items, key=lambda x: x['name'])
}
结果如下:
{
'Strawberries': {'price': 5.0, 'quantity': []},
'Coffee': {'price': 11.23, 'quantity': []},
'Green Tea': {'price': 3.11, 'quantity': []}
}
IndexError: list index out of range
我不确定为什么我只能访问我尝试创建的子字典中的一个值的文章。
如有任何建议,我们将不胜感激。 谢谢!
在我看来,这不是 groupby
的最佳用例。在 items
.
(default)dict
更容易
from collections import defaultdict
result = defaultdict(lambda: {'price': None, 'quantity': 0})
for item in items:
subdict = result[item['name']]
subdict['quantity'] += 1
subdict['price'] = item['price']
输出:
>>> result
defaultdict(<function __main__.<lambda>()>,
{'Strawberries': {'price': 5.0, 'quantity': 3},
'Coffee': {'price': 11.23, 'quantity': 2},
'Green Tea': {'price': 3.11, 'quantity': 1}})
(如果价格被商品的最后一次看到的价格覆盖。如果您不希望具有相同名称的商品的价格不明确,这是可以的。)
编辑:没有 defaultdict
result = {}
for item in items:
result.setdefault(item['name'], {'price': item['price'], 'quantity': 0})['quantity'] += 1
您得到空白列表或索引错误的原因是因为您的 article
对象是一个迭代器,它在第一次调用 list(article)
时被完全消耗。
当你第一次拿到价格时,价格是正确的,但数量是空的,因为你已经消费了article
。相比之下,当您先获取数量然后获取第一个项目的价格时,第二次调用 list(article)
会生成一个空列表,您尝试对其进行索引但不能,因为没有项目。
这是 groupby
的解决方案,您可以在其中保存 list(article)
并将其用于价格和数量。
grouped = {}
for name, article in groupby(items, key=lambda itm: itm["name"]):
products = list(article)
grouped[name] = {
"price": products[0]["price"],
"quantity": len(products),
}
编辑:如评论中所述,这假定您的 items
列表按照您想要的顺序排列。通常您会希望以有意义的方式对传递给 groupby()
的可迭代对象进行排序。但也许您只是想将连续的项目组合在一起,即使相同的项目出现在列表的后面。