Add assignment 5 content
This commit is contained in:
parent
d81425a781
commit
bfdc5dc93b
8
assignments/A5/.idea/.gitignore
vendored
Normal file
8
assignments/A5/.idea/.gitignore
vendored
Normal 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
|
8
assignments/A5/.idea/A5.iml
Normal file
8
assignments/A5/.idea/A5.iml
Normal 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>
|
@ -0,0 +1,6 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<settings>
|
||||
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||
<version value="1.0" />
|
||||
</settings>
|
||||
</component>
|
4
assignments/A5/.idea/misc.xml
Normal file
4
assignments/A5/.idea/misc.xml
Normal 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>
|
8
assignments/A5/.idea/modules.xml
Normal file
8
assignments/A5/.idea/modules.xml
Normal 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>
|
6
assignments/A5/.idea/vcs.xml
Normal file
6
assignments/A5/.idea/vcs.xml
Normal 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
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
121
assignments/A5/readcsv.py
Normal 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
4
assignments/A5/test1.csv
Normal file
@ -0,0 +1,4 @@
|
||||
name, age, eye colour
|
||||
Bob, 5, blue
|
||||
Mary, 27, brown
|
||||
Vij, 54, green
|
|
3
assignments/A5/test2.csv
Normal file
3
assignments/A5/test2.csv
Normal file
@ -0,0 +1,3 @@
|
||||
name, 100
|
||||
teddy, 500
|
||||
lovely, 1000
|
|
93
assignments/A5/test_readcsv.py
Normal file
93
assignments/A5/test_readcsv.py
Normal 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"))
|
1751
assignments/A5/test_readcsv_bigdata.py
Normal file
1751
assignments/A5/test_readcsv_bigdata.py
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user