Add assignment 5 content

This commit is contained in:
Isaac Shoebottom 2022-11-18 16:28:38 -04:00
parent d81425a781
commit bfdc5dc93b
12 changed files with 3012 additions and 0 deletions

8
assignments/A5/.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View File

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10 (python-venv)" project-jdk-type="Python SDK" />
</project>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/A5.iml" filepath="$PROJECT_DIR$/.idea/A5.iml" />
</modules>
</component>
</project>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
</component>
</project>

1000
assignments/A5/2014-1000.csv Normal file

File diff suppressed because one or more lines are too long

121
assignments/A5/readcsv.py Normal file
View File

@ -0,0 +1,121 @@
def read_csv(filename):
"""Read a CSV file, return list of rows"""
import csv
with open(filename, 'rt', newline='') as f:
reader = csv.reader(f, skipinitialspace=True)
return [row for row in reader]
def header_map(headers):
"""
Read a list, and convert it to a dictionary where the key is each element of the given list and the value is
its position in the list
:param headers: List
:return: Dict
"""
header_dict = dict()
i = 0
for header in headers:
header_dict[header] = i
i = i + 1
return header_dict
def select(table, search_items):
"""
Read the set in the second argument and search through the table in the first argument and return the
columns that match the query in the search items
:param table: List
:param search_items: List
:return: List
"""
header_numbers = header_map(table[0])
ret_list = list()
columns = list()
for item in search_items:
columns.append(header_numbers[item])
columns.sort()
for item in table:
lst = list()
for number in columns:
lst.append(item[number])
ret_list.append(lst)
return ret_list
def row2dict(hmap, row):
"""
Convert a row in the second argument, given the headers in the first argument to a dictionary which uses the
headers as keys and the row data as values
:param hmap: Dictionary
:param row: List
:return: Dictionary
"""
ret_dict = dict()
for key in hmap:
ret_dict[key] = row[hmap[key]]
return ret_dict
def check_row(row, query):
"""
Check the row in the first argument passes a query in the second argument. The second argument is a formatted
tuple where the first element in the tuple is a column name, the second is an operation (==, <=, >=, AND,
OR) and the third element is a condition, numeric or string matching. (ex: is age == 34, is color == blue). AND
and OR are special in that you can pass in recursive tuples (left and right argument are tuples) that will also
be evaluated recursively
:param row: List
:param query: Tuple
:return: Boolean
"""
def perform_operation(op, var, cond):
if type(var) is str:
if var.isnumeric():
var = int(var)
if type(cond) is str:
if cond.isnumeric():
cond = int(cond)
if op == '==':
return var == cond
elif op == '>=':
return var >= cond
elif op == '<=':
return var <= cond
elif op == 'OR':
return perform_operation(var[1], row[var[0]], var[2]) or perform_operation(cond[1], row[cond[0]], cond[2])
elif op == 'AND':
return perform_operation(var[1], row[var[0]], var[2]) and perform_operation(cond[1], row[cond[0]], cond[2])
else:
return False
if type(query[0]) and type(query[2]) is tuple:
return perform_operation(query[1], query[0], query[2])
elif query[2] not in row:
stringify = str(query[2])
return perform_operation(query[1], row[str(query[0])], stringify)
else:
return perform_operation(query[1], row[str(query[0])], row[query[2]])
def filter_table(table, query):
"""
This function takes a table of csv values, and performs the query to filter out the rows that do not match the query
:param table: List
:param query: Tuple
:return: List
"""
header_row = header_map(table[0])
data_rows = table[1:]
result = list()
result.append(table[0])
for row in data_rows:
data_dict = row2dict(header_row, row)
if check_row(data_dict, query):
result.append(row)
return result

4
assignments/A5/test1.csv Normal file
View File

@ -0,0 +1,4 @@
name, age, eye colour
Bob, 5, blue
Mary, 27, brown
Vij, 54, green
1 name age eye colour
2 Bob 5 blue
3 Mary 27 brown
4 Vij 54 green

3
assignments/A5/test2.csv Normal file
View File

@ -0,0 +1,3 @@
name, 100
teddy, 500
lovely, 1000
1 name 100
2 teddy 500
3 lovely 1000

View File

@ -0,0 +1,93 @@
from readcsv import read_csv
from readcsv import header_map
from readcsv import select
from readcsv import row2dict
from readcsv import check_row
from readcsv import filter_table
table = read_csv('test1.csv')
sampledata = read_csv('2014-1000.csv')
def test_read_csv():
assert read_csv('test1.csv') == [['name', 'age', 'eye colour'],
['Bob', '5', 'blue'],
['Mary', '27', 'brown'],
['Vij', '54', 'green']]
def test_header_map_1():
hmap = header_map(table[0])
assert hmap == {'name': 0, 'age': 1, 'eye colour': 2}
def test_select_1():
assert select(table, {'name', 'eye colour'}) == [['name', 'eye colour'],
['Bob', 'blue'],
['Mary', 'brown'],
['Vij', 'green']]
def test_row2dict():
hmap = header_map(table[0])
assert row2dict(hmap, table[1]) == {'name': 'Bob', 'age': '5', 'eye colour': 'blue'}
def test_check_row():
row = {'name': 'Bob', 'age': '5', 'eye colour': 'blue'}
assert check_row(row, ('age', '==', 5))
assert not check_row(row, ('eye colour', '==', 5))
assert check_row(row, ('eye colour', '==', 'blue'))
assert check_row(row, ('age', '>=', 4))
assert check_row(row, ('age', '<=', 1000))
def test_check_row_logical():
row = {'name': 'Bob', 'age': '5', 'eye colour': 'blue'}
assert check_row(row, (('age', '==', 5), 'OR', ('eye colour', '==', 5)))
assert not check_row(row, (('age', '==', 5), 'AND', ('eye colour', '==', 5)))
def test_filter_table1():
assert filter_table(table, ('age', '>=', 0)) == [['name', 'age', 'eye colour'],
['Bob', '5', 'blue'],
['Mary', '27', 'brown'],
['Vij', '54', 'green']]
assert filter_table(table, ('age', '<=', 27)) == [['name', 'age', 'eye colour'],
['Bob', '5', 'blue'],
['Mary', '27', 'brown']]
assert filter_table(table, ('eye colour', '==', 'brown')) == [['name', 'age', 'eye colour'],
['Mary', '27', 'brown']]
assert filter_table(table, ('name', '==', 'Vij')) == [['name', 'age', 'eye colour'],
['Vij', '54', 'green']]
def test_filter_table2():
assert filter_table(table, (('age', '>=', 0), 'AND', ('age', '>=', '27'))) == [['name', 'age', 'eye colour'],
['Mary', '27', 'brown'],
['Vij', '54', 'green']]
assert filter_table(table, (('age', '<=', 27), 'AND', ('age', '>=', '27'))) == [['name', 'age', 'eye colour'],
['Mary', '27', 'brown']]
assert filter_table(table, (('eye colour', '==', 'brown'),
'OR',
('name', '==', 'Vij'))) == [['name', 'age', 'eye colour'],
['Mary', '27', 'brown'],
['Vij', '54', 'green']]
# Student Tests
def test_check_row_2():
row = {'name': 'Bob', 'age': '5', 'eye colour': 'blue'}
assert not check_row(row, ('age', '===', 5))
def test_check_row_3():
# Could not get test to pass, but included for completeness of tests
table2 = read_csv('test2.csv')
assert check_row(table2[1], ("100", "==", "500"))

File diff suppressed because it is too large Load Diff