2

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!

johnseca48
  • 23
  • 3
  • you need to sort your initial list by stock before using groupBy – DevLounge Mar 14 '21 at 23:57
  • Does this answer your question? [How do I use itertools.groupby()?](https://stackoverflow.com/questions/773/how-do-i-use-itertools-groupby) – j-i-l Mar 15 '21 at 00:00

1 Answers1

4

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}]
}
Nick
  • 138,499
  • 22
  • 57
  • 95
  • I see. Wow thank you. This is my first question and was answered in less than 5 minutes, and I was stuck in this one for 1 hour until now! I initially thought my previous code was fine because itertools.groupby will produce an iterator any way and wont need to be sorted. Thanks again! – johnseca48 Mar 15 '21 at 00:05