Skip to main content

Grouping a Collection

Grouping means sorting elements into buckets. You choose a key for every element, and all elements with the same key land in the same bucket.

The key is computed by a small expression that takes one element and returns its key. For example, the first letter of a word.

Python has no built-in group_by method on lists. The natural way to group is a dictionary whose keys are the group keys and whose values are lists of elements. You fill it with a for loop and setdefault(), or you let collections.defaultdict(list) create the empty lists for you.

A dictionary keeps its entries in insertion order, so the groups appear in the order their first elements were seen. The printed output always looks the same.


Group By Key

The simplest grouping keeps the elements as they are and only decides which bucket each one goes to.

setdefault(key, []) returns the list stored under the key, and stores a new empty list first when the key is not there yet. So groups.setdefault(key, []).append(w) works even for the first element of a group. The elements inside a group keep the order they had in the input.

Sometimes you want to change the elements while grouping, for example store them in upper case. Compute the key, compute the new value, and append the new value to the group. With a defaultdict(list) a plain groups[key].append(value) is enough.

Group words by first letter

The key is the first letter of the word, w[0], made upper case with upper(). Words that start with the same letter end up in the same list.

Prompt
Group the words one, two, three, four, five by their upper-case first letter. Fill a dictionary from letter to list of words with a loop and setdefault(). Print the dictionary.
Output: complete Python program
Group words by first letter

Group and change the values

The key is the lower-case first letter. The stored value is the whole word in upper case. A defaultdict(list) starts every new group as an empty list; dict() turns it back into a plain dictionary for a clean print.

Prompt
Group the words one, two, three, four, five by their lower-case first letter. Store each word in its group in upper case, not as it was. Use a collections.defaultdict of lists, then print it as a plain dictionary.
Output: complete Python program
Group and change the values

Count Each Group

Often you do not need the elements of each group, only how many there are.

The standard library has a tool for exactly this: collections.Counter. Give it the keys and it returns a dictionary-like object from key to count. Reading a key that is not in a Counter gives 0.

When it is printed, a Counter shows the biggest counts first.

Count words per first letter

Every word is turned into its first letter, and Counter counts the letters. The letters t and f both appear twice, so they are printed before o.

Prompt
Count how many of the words one, two, three, four, five start with each letter. Use collections.Counter on the first letters and print the counter.
Output: complete Python program
Count words per first letter

Fold and Reduce per Group

Folding a group means combining its elements into one value, step by step. A running total is the classic example: start at 0 and add each element.

Python has no fold() or aggregate() on groups. Use a dictionary that holds the running value of every group. For each element, compute its key and update the value stored under that key.

When the running value has a starting value, such as 0 for a sum, get(key, 0) gives you that start for a missing key. When the first element itself must start the value, check with the in operator whether the key exists yet; get(key), which gives None for a missing key, works too.

Sum each group

Each number is put in the group "even" or "odd" and added to that group's sum. sums.get(key, 0) starts a new key at 0, so no special case is needed.

Prompt
Take the numbers 3, 4, 5, 6, 7, 8 and put each one in the group "even" or "odd". Instead of keeping the numbers, add each number to the running sum of its group in a dictionary, using get(key, 0) as the start. Print the dictionary.
Output: complete Python program
Sum each group

Build a string per group

The first number of a group starts the string. Every later number is joined with "+". The key not in chains check tells the two cases apart. str() turns a number into text.

Prompt
Take the numbers 3, 4, 5, 6, 7, 8 and put each one in the group "even" or "odd". For each group build a string step by step: the first number starts the string, and every later number is added with a "+" in front, giving text like 3+5+7. Print the dictionary from group name to string.
Output: complete Python program
Build a string per group