Chapter 6
The interior function handles our essential recursive definition. An empty collection
returns the provided dictionary. A non-empty collection is parsed into a head and
tail. The head is used to update the dictionary. The tail is then used, recursively,
to update the dictionary with all remaining elements.
We can't easily use Python's default values to collapse this into a single function.
We cannot use the following command snippet:
def group_by(key, data, dictionary=defaultdict(list)):
If we try this, all uses of the group_by() function share one common
defaultdict(list) object. Python builds default values just once. Mutable
objects as default values rarely do what we want. Rather than try to include more
sophisticated decision-making to handle an immutable default value (like None),
we prefer to use a nested function definition. The wrapper() function properly
initializes the arguments to the interior function.
We can group the data by distance as follows:
binned_distance = lambda leg: 5*(leg[2]//5)
by_distance= group_by(binned_distance, trip)
We've defined simple, reusable lambda which puts our distances into 5 nm bins.
We then grouped the data using the provided lambda.
We can examine the binned data as follows:
import pprint
for distance in sorted(by_distance):
print(distance)
pprint.pprint(by_distance[distance])
Following is what the output looks like:
0.0
[((35.505665, -76.653664), (35.508335, -76.654999), 0.1731),
((35.028175, -76.682495), (35.031334, -76.682663), 0.1898),
((25.4095, -77.910164), (25.425833, -77.832664), 4.3155),
((25.0765, -77.308167), (25.080334, -77.334), 1.4235)]
5.0
[((38.845501, -76.537331), (38.992832, -76.451332), 9.7151),
((34.972332, -76.585167), (35.028175, -76.682495), 5.8441),
((30.717167, -81.552498), (30.766333, -81.471832), 5.103),
((25.471333, -78.408165), (25.504833, -78.232834), 9.7128),
((23.9555, -76.31633), (24.099667, -76.401833), 9.844)] ...
125.0
[((27.154167, -80.195663), (29.195168, -81.002998), 129.7748)]