简体   繁体   中英

Python - itertools.groupby

Just having trouble with itertools.groupby. Given a list of dictionaries,

my_list = [
{'name': 'stock1', 'price': 200, 'shares': 100},
{'name': 'stock2', 'price': 1.2, 'shares': 1000},
{'name': 'stock3', 'price': 0.05, 'shares': 200000},
{'name': 'stock1', 'price': 200.2, 'shares': 50}]

From this list, I was hoping to create a dictionary, where the key is the name of the stock, and the value is a list of dictionaries of that stock, for example:

{'stock1': [{'name': 'stock1', 'price': 200, 'shares': 100}, {'name': 'stock1', 'price': 200.2, 'shares': 50}] }

I ran this code:

by_name = { name: list(items) for name, items in itertools.groupby(
            my_list, key=lambda x: x['name'])}

, and this is the result I got:

 {'stock1': [{'name': 'stock1', 'price': 200.2, 'shares': 50}],
 'stock2': [{'name': 'stock2', 'price': 1.2, 'shares': 1000}],
 'stock3': [{'name': 'stock3', 'price': 0.05, 'shares': 200000}]}

For stock1, I'm expecting 2 items in the list but it only has the latest entry from the original my_list. Can anyone please point out where the mistake is? Thank you!

That isn't how itertools.groupby works. From the manual:

It generates a break or new group every time the value of the key function changes (which is why it is usually necessary to have sorted the data using the same key function)

So to achieve the type of grouping you want, you need to sort my_list first:

import itertools

my_list = [
{'name': 'stock1', 'price': 200, 'shares': 100},
{'name': 'stock2', 'price': 1.2, 'shares': 1000},
{'name': 'stock3', 'price': 0.05, 'shares': 200000},
{'name': 'stock1', 'price': 200.2, 'shares': 50}
]

my_list.sort(key=lambda x:x['name'])

by_name = { name: list(items) for name, items in itertools.groupby(
            my_list, key=lambda x: x['name'])}

print(by_name)

Output

{'stock1': [{'name': 'stock1', 'price': 200, 'shares': 100},
            {'name': 'stock1', 'price': 200.2, 'shares': 50}],
 'stock2': [{'name': 'stock2', 'price': 1.2, 'shares': 1000}],
 'stock3': [{'name': 'stock3', 'price': 0.05, 'shares': 200000}]
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM