So, what you have will work usually, but may have an error in the case of multiple courses having the same location/date/time. This code is assuming that no two courses will write in the same place/date/time, which is probably true, but not something we want to depend on.

But consider the following approach. Before we loop over every exam section for a course and create exam objects for it, we can pre-process all the exam sections for a course and consolidate them. Then we can just do the loop exactly like it was before, without any changes. Essentially this simulates what used to happen, as if OpenData returned us a list of exam objects with sections already grouped together.

Here's a rough outline of the code:

At https://github.com/UWFlow/rmc/pull/149/files#diff-b5dbc515bd4f996bd222452c19630819L351:

```python
grouped_sections = group_similar_exam_sections(
        exam_data.get('sections', []))
for section_data in grouped_sections:
    # Original code, unchanged
```

And `group_similar_exam_sections`:

```python
def group_similar_exam_sections(exam_sections):
    """Groups together exam sections that have the same date, time, and location.

    Args:
        exam_sections: A list of sections for an exam as returned by OpenData's
            examschedule.json endpoint.

    Returns a consolidated list of sections in the same format, where each item
        has a unique date/time/location.
    """
    # You can figure out how to code this :)
```

This has the following advantages:

- It can be tested. `group_similar_exam_sections` is a nicely-factored function with a clear input and clear output, with no hairy dependencies to mock/stub. We can easily write unit tests for it.
- Its runtime is not O(N^2), as it was in the code before, where for each section we loop over every element in processed_exams.
- You only run the date-formatting code once on each consolidated group of sections, instead of on every section.
- It's a functional style, where we take data from one function, then pass it off to another function. There is less mutation of data, but just converting data from one form to another. (Hopefully you guys will learn some Scheme in 2nd year. Sad they took that away from CS 138, but learning to think in a functional style is very helpful for a lot of applications, in particular parallel programming.)
- Similar to the above, but not necessary in this case, it's easily parallelizeable. You can easily imagine splitting off the processing of each course into its own thread without shared variables/race conditions between threads.
- It's nicely separated from the other code and breaks up the processing into independent steps with clear interfaces between the steps, and is thus easier to reason about and easier to remove.

This is also a great foray to writing some unit tests. :) Just create another file, `processor_test.py`, in the same directory as `processor.py`. Take a look at `util_test.py` to see some examples of unit tests. You can run your tests as follows:

```shell
PYTHONPATH=.. nosetests -v --nocapture data/processor_test.py
```

You can run all our tests by running `make test`.

Does that make sense? Let me know if there are any unclear points.