· 9 years ago · Jan 08, 2017, 09:28 PM
1class Table():
2 '''A class to represent a SQuEaL table'''
3
4 def __init__(self, dict_of_info={}):
5 '''(Table, dict of: {str: list}***if present) -> NoneType
6 This function instantiates a new Table object and sets an optional
7 dictionary.
8 '''
9 # Initialize the dictionary that contains the information according
10 # to the parameter
11 self._dict_of_info = dict_of_info
12
13 def set_dict(self, new_dict):
14 '''(Table, dict of {str: list of str}) -> NoneType
15
16 Populate this table with the data in new_dict.
17 The input dictionary must be of the form:
18 column_name: list_of_values
19 '''
20 # Set the embedded dictionary to the parameter dictionary
21 self._dict_of_info = new_dict
22
23 def copy_table(self):
24 '''(Table) -> NoneType
25 Given a table, this function creates a shallow copy of the dictionary
26 and makes a copy table
27 '''
28 # Create a shallow copy of the embedded dictionary
29 copy_dictionary = self._dict_of_info.copy()
30 # Create a copy table with the copy dictionary
31 copy_table = Table(copy_dictionary)
32 # Return the copied table
33 return copy_table
34
35 def initialize(self, colnames):
36 '''(Table, list) -> NoneType
37 Given the colnames, this method initializes the colnames where each
38 element in the list of colnames is a key in the embedded dictionary
39 '''
40 # Loop until there are no other column names left in the list
41 for next_colname in colnames:
42 # Initialize the column with an empty list
43 self._dict_of_info[next_colname] = []
44
45 def add_row(self, colnames, list_of_elements):
46 '''(Table, list, list) -> NoneType
47 Given the colnames, and the list_of_elements this method populates the
48 embedded dictionary present in the Table object
49 REQ: the elements present in colnames must be a valid key in the
50 embedded dictionary
51 '''
52 # Loop until index is less than the len of the list
53 for index in range(len(list_of_elements)):
54 # Set the name of the column and the element to update
55 colname = colnames[index]
56 element = list_of_elements[index]
57 if element != '':
58 # Add the list version of the element to the columns
59 self._dict_of_info[colname] += [element]
60
61 def get_dict(self):
62 '''(Table) -> dict of {str: list of str}
63
64 Return the dictionary representation of this table. The dictionary keys
65 will be the column names, and the list will contain the values
66 for that column.
67 '''
68 # Return the embedded dictionary
69 return self._dict_of_info
70
71 def num_rows(self):
72 '''(Table, dict of: {str: list}***if present) -> int
73 Given the Table object this function counts the number of rows that are
74 present in the virtual Table and returns the value
75 REQ: The option parameter that gets passed in must contain the method
76 .keys() and must be a dict of: {str: list}
77 '''
78 # Cast the keys present in the dictionary with the help of the .keys()
79 # method
80 list_of_keys = list(self._dict_of_info.keys())
81 # Try to get the length of the first column if it exists
82 try:
83 rows = len(self._dict_of_info[list_of_keys[0]])
84 except IndexError:
85 # If not set the number of row to 0
86 rows = 0
87 # Return the number of rows present in the list
88 return rows
89
90 def print_csv(self):
91 '''(Table) -> NoneType
92 Print a representation of table in csv format.
93 '''
94 # no need to edit this one, but you may find it useful (you're welcome)
95 dict_rep = self.get_dict()
96 columns = list(dict_rep.keys())
97 print(','.join(columns))
98 rows = self.num_rows()
99 for i in range(rows):
100 cur_column = []
101 for column in columns:
102 cur_column.append(dict_rep[column][i])
103 print(','.join(cur_column))
104
105 def duplicate_elements(self, iterations, mode):
106 '''(Table, int, int) -> NoneType
107 Given the iterations, and the mode, this function
108 duplicates the value in each key based on the mode.
109 MODE1 -> for table 1 on the left
110 MODE2 -> for table 2 on the right
111 REQ: mode must be either 1 or 2
112 REQ: iterations>0
113 '''
114 # Execute a duplication in the form -> [1,2] to [1, 1, 1, 2, 2, 2] iter
115 # = 3 if the mode is 1.
116 if mode == 1:
117 # Loop until there are no keys left in the dictionary
118 for key in self._dict_of_info:
119 # Get the list of info elements from the self._dict_of_info
120 list_of_info_elements = self._dict_of_info[key]
121 # Determine the length of the list
122 lengh_of_column = len(list_of_info_elements)
123 # Initialize the count to aid in ending the loop
124 count = 0
125 if iterations == 0:
126 self._dict_of_info[key] = []
127 else:
128 # Loop until count does not reach the length of the list
129 while count < lengh_of_column:
130 # Get the element that should be duplicated
131 element_to_duplicate = (self._dict_of_info
132 [key][count:count+1])
133 # Slice the rest of the elements other than the
134 # duplicate
135 rest_elements = self._dict_of_info[key][count+1:]
136 # Slice the first list of elements
137 first_elements = self._dict_of_info[key][:count+1]
138 # Set the key value to the sum of the first elements,
139 # the element_to_duplicate iterated one time less than
140 # the column length of the second table.
141 self._dict_of_info[key] = (first_elements +
142 element_to_duplicate *
143 (iterations - 1) +
144 rest_elements)
145 # Add the number of iterations to count and substract
146 # (iter-1)
147 # from length_of_column such that the loops only iters
148 # for the inital length of the column
149 count += iterations
150 lengh_of_column += iterations - 1
151 # Execute a duplication in the form -> [1,2] to [1, 2, 1, 2, 1, 2]
152 # iter = 3 if the mode is 2
153 elif mode == 2:
154 # Loop until there are no keys left in the self._dict_of_info
155 for key in self._dict_of_info:
156 # Get the list_of_info_elements
157 list_of_info_elements = self._dict_of_info[key]
158 # Duplite the whole list based on the value of iterations
159 self._dict_of_info[key] = list_of_info_elements*iterations
160
161 def select_columns(self, columns_list):
162 '''(Table, list) -> NoneType
163 Given the _dict_of_info, and the columns_list this function only keeps
164 the the column names(keys) that are present in the list of columns_list
165 REQ: All the elements present in the columns_list must be a valide
166 column name that is present as a key in the _dict_of_info
167 REQ: len(_dict_of_info) > 0
168 REQ: len(columns_list) > 0
169 '''
170 # Initialize the dictionary that should be returned
171 query_dict = {}
172 # Loop until there no elements left in the list of column names
173 for next_column in columns_list:
174 # Make the return dictionary as a copy of the parameter dictionary
175 # if the element is a '*'
176 if next_column == '*':
177 query_dict = self._dict_of_info.copy()
178 # Else populate the return dictionary with the key and the
179 # corresponding value of the paramenter dictionary
180 elif next_column in self._dict_of_info:
181 query_dict[next_column] = self._dict_of_info[next_column]
182 self._dict_of_info = query_dict
183
184 def delete_rows(self, wanted_rows):
185 '''(dict of {}, str, list) -> NoneType
186 Given colnames, and a list of wanted_rows this function
187 deletes all the un-wanted rows present in every column other than
188 colnames
189 REQ: The value mapped to each key must be a list of the same length
190 REQ: The value present in the wanted_rows must be valid indices
191 '''
192 # Loop until every list mapped under every key is mutated
193 for next_key in self._dict_of_info:
194 count = 0
195 length_of_column = len(self._dict_of_info[next_key])
196 # Initialize a variable which keeps track of deleted objects.
197 displacement = 0
198 # Loop until the index(count) is less than the length of the column
199 while (count) < length_of_column:
200 # If the (actual index) is not in the list of wanted rows
201 if (count+displacement) not in wanted_rows:
202 # delete the element from the column
203 del self._dict_of_info[next_key][count]
204 # Decrease the length of the column by one
205 length_of_column -= 1
206 # Add to the dicplacement
207 displacement += 1
208 # Else add one to index(count)
209 else:
210 count += 1
211
212 def merge(self, Table2):
213 '''(Table, Table) -> NoneType
214 Given another table this method merges the keys of the paremter
215 dictionary to the embedded dictionary within
216 REQ: the keys of the Table2 must not overlap with the keys of the
217 embedded dictionary
218 '''
219 # Update the embedded dictionary with information from Table2
220 self._dict_of_info.update(Table2._dict_of_info)
221
222 def clear_table(self):
223 '''(Table) -> NoneType
224 This method merely clears the whole table
225 '''
226 # Clear the whole table
227 self._dict_of_info = {}
228
229 def determine_wanted_rows(self, colname1, operator, value):
230 '''(Table, str, str, str) -> list
231 Given the dictionary, colname1, operator and value this funtion
232 determines the wanted rows where the values in colname1 at index is
233 either equal to or greater than the _dict_of_info[value] if value is
234 key.
235 REQ: len(_dict_of_info) > 0
236 REQ: colname1 and colname 2 must be present in _dict_of_info as keys
237 REQ: The operator must be either '=' or '>' and none other
238 '''
239 # Initialize the wanter_index list and the count
240 wanted_rows = list()
241 count = 0
242 # Set the length_of_column to the length of the list of mapped to the
243 # key
244 length_of_column = len(self._dict_of_info[colname1])
245 # Check if the operator given as a parameter is a '='
246 if operator == '=':
247 # Loop until count is less than the length of the column
248 while count < length_of_column:
249 # Set the left term accordingly
250 left_term = self._dict_of_info[colname1][count]
251 # Check if the value given is a key in the dictionary if so set
252 # the right term to the value at indec(count) of the key
253 try:
254 right_term = self._dict_of_info[value][count]
255 except KeyError:
256 right_term = value
257 # Try to cast the values into a floating point.
258 # If a ValueError is raised then simply pass
259 try:
260 left_term = float(left_term)
261 right_term = float(right_term)
262 except ValueError:
263 pass
264 # Add the index(count) to the wanted list if the left term is
265 # equal to the right term.
266 if left_term == right_term:
267 wanted_rows.append(count)
268 # Add to the index(count)
269 count += 1
270 # Check if the operator given as a parameter is a '>'
271 elif operator == '>':
272 # Loop until count is less than the length of the column
273 while count < length_of_column:
274 # Set the right term and the left term accordingly
275 left_term = self._dict_of_info[colname1][count]
276 # Check if the value given is a key in the dictionary if so
277 # set the right term to the value at indec(count) of the key
278 try:
279 right_term = self._dict_of_info[value][count]
280 except KeyError:
281 right_term = value
282 # Try to cast the values into a floating point.
283 # If a ValueError is raised then simply pass
284 try:
285 left_term = float(left_term)
286 right_term = float(right_term)
287 except ValueError:
288 pass
289 # If the left term is greater than the right term
290 if left_term > right_term:
291 # Add the index(count) to the wanted_rows list.
292 wanted_rows.append(count)
293 # Add to the index(count) to keep checking through the lists
294 count += 1
295 # Return the wanted rows
296 return wanted_rows
297
298
299class Database():
300 '''A class to represent a SQuEaL database'''
301
302 def __init__(self, dict_of_name_tables={}):
303 '''(Database, dict of: {str: Table}) -> NoneType
304 This function instantiates a Database object
305 '''
306 # Initialize the dictionary that holds the tables and
307 self._dict_of_name_tables = dict_of_name_tables
308
309 def set_dict(self, new_dict):
310 '''(Database, dict of {str: Table}) -> NoneType
311
312 Populate this database with the data in new_dict.
313 new_dict must have the format:
314 table_name: table
315 '''
316 # Set the dictionary with a new one
317 self._dict_of_name_tables = new_dict
318
319 def add_table(self, table_name, table):
320 '''(Database, str, Table) -> NoneType
321 Given the name of the table and the Table object, this method adds a
322 Table object to the Database
323 REQ: table_name must be unique
324 '''
325 # Add the table mapped to the table_name
326 self._dict_of_name_tables[table_name] = table
327
328 def get_table(self, table_name):
329 '''(Database, str) -> Table
330 Given the table name this method returns the table object that is
331 mapped to the table_name specified
332 REQ: table_name should be a valid entry in the database
333 '''
334 # Get the table object from the the database
335 table_to_return = self._dict_of_name_tables[table_name]
336 # Return the table object
337 return table_to_return
338
339 def get_dict(self):
340 '''(Database) -> dict of {str: Table}
341
342 Return the dictionary representation of this database.
343 The database keys will be the name of the table, and the value
344 with be the table itself.
345 '''
346 # Return the embedded dictionary
347 return self._dict_of_name_tables