-
Notifications
You must be signed in to change notification settings - Fork 0
/
database.py
119 lines (90 loc) · 4.53 KB
/
database.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
"""A database encapsulating collections of near-Earth objects and their
close approaches.
A `NEODatabase` holds an interconnected data set of NEOs and close approaches.
It provides methods to fetch an NEO by primary designation or by name, as well
as a method to query the set of close approaches that match a collection of
user-specified criteria.
Under normal circumstances, the main module creates one NEODatabase from the
data on NEOs and close approaches extracted by `extract.load_neos` and
`extract.load_approaches`.
You'll edit this file in Tasks 2 and 3.
"""
class NEODatabase:
"""A database of near-Earth objects and their close approaches.
A `NEODatabase` contains a collection of NEOs and a collection of close
approaches. It additionally maintains a few auxiliary data structures to
help fetch NEOs by primary designation or by name and to help speed up
querying for close approaches that match criteria.
"""
def __init__(self, neos, approaches):
"""Create a new `NEODatabase`.
As a precondition, this constructor assumes that the collections
of NEOs and close approaches haven't yet been linked - that is, the
`.approaches` attribute of each `NearEarthObject` resolves to an empty
collection, and the `.neo` attribute of each `CloseApproach` is None.
However, each `CloseApproach` has an attribute (`._designation`) that
matches the `.designation` attribute of the corresponding NEO. This
constructor modifies the supplied NEOs and close approaches to link
them together - after it's done, the `.approaches` attribute of each
NEO has a collection of that NEO's close approaches, and the `.neo`
attribute of each close approach references the appropriate NEO.
:param neos: A collection of `NearEarthObject`s.
:param approaches: A collection of `CloseApproach`es.
"""
self._neos = neos
self._approaches = approaches
# Additonal temporary dicts:
self.designations = {}
self.names = {}
for neo in self._neos:
# add neo to designations temporary dict
self.designations[neo.designation] = neo
# add neo to names temporary dict if it has a name
if neo.name != '':
self.names[neo.name] = neo
for approach in self._approaches:
approach.neo = self.designations.get(approach._designation)
self.designations[approach._designation] \
.approaches.append(approach)
def get_neo_by_designation(self, designation):
"""Find and return an NEO by its primary designation.
If no match is found, return `None` instead.
Each NEO in the data set has a unique primary designation, as a string.
The matching is exact - check for spelling and capitalization if no
match is found.
:param designation: The primary designation of the NEO to search for.
:return: The `NearEarthObject` with the desired primary designation,
or `None`.
"""
return self.designations.get(designation)
def get_neo_by_name(self, name):
"""Find and return an NEO by its name.
If no match is found, return `None` instead.
Not every NEO in the data set has a name. No NEOs are associated with
the empty string nor with the `None` singleton.
The matching is exact - check for spelling and capitalization if no
match is found.
:param name: The name, as a string, of the NEO to search for.
:return: The `NearEarthObject` with the desired name, or `None`.
"""
return self.names.get(name)
def query(self, filters=()):
"""Query close approaches to generate those that match a collection of
filters.
This generates a stream of `CloseApproach` objects that match all of
the provided filters.
If no arguments are provided, generate all known close approaches.
The `CloseApproach` objects are generated in internal order, which
isn't guaranteed to be sorted meaningfully, although is often sorted
by time.
:param filters: A collection of filters capturing user-specified
criteria.
:return: A stream of matching `CloseApproach` objects.
"""
if not filters:
for approach in self._approaches:
yield approach
else:
for approach in self._approaches:
if all(map(lambda x: x(approach), filters)):
yield approach