Last active
December 19, 2015 00:19
-
-
Save 3kwa/5868197 to your computer and use it in GitHub Desktop.
No standard library allowed exercise :S
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
__pycache__ | |
details.csv | |
errors.csv | |
*.pyc | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
WITHOUT using the standard library. | |
Write a program that reads orders and trades from csv files in ONE PASS ONLY, | |
never keeping in memory more than ONE ORDER AND TRADE AT A TIME and writes | |
trades with matching orders to the file details.csv, trades with no matching | |
order to the file errors.csv. | |
Orders and trades are sorted by order_id (first item). | |
""" | |
def main(): | |
orders, trades = map(reader, ('orders', 'trades')) | |
detail, error = map(writer, ('details', 'errors')) | |
doit(orders, trades, detail, error) | |
def doit(orders, trades, detail, error): | |
""" | |
For testability's sake | |
""" | |
process = inject(detail, error) | |
order = orders.next() | |
for trade in trades: | |
while not process(trade, order): | |
try: | |
order = orders.next() | |
except StopIteration: | |
error(*trade) | |
break | |
def inject(detail, error): | |
""" | |
Faster and arguably more readable than a callable class | |
""" | |
def closure(trade, order): | |
""" | |
trade lag order => error and return True | |
trade match order => detail return True | |
order lag trade => return False | |
""" | |
trade_order_id, trade_id, trade_data = trade | |
order_id, order_data = order | |
if order_id > trade_order_id: | |
error(trade_order_id, trade_id, trade_data) | |
elif order_id == trade_order_id: | |
detail(order_id, trade_id, order_data, trade_data) | |
else: | |
return False | |
return True | |
return closure | |
def reader(filename): | |
""" | |
Ad hoc csv file reader (iterator) | |
""" | |
with open(csv(filename)) as f: | |
for line in f: | |
yield line[:-1].replace(' ', '').split(',') | |
def writer(filename): | |
""" | |
Ad hoc callable csv writer | |
""" | |
file_ = open(csv(filename), 'w') | |
def closure(*args): | |
print filename, args | |
file_.write(','.join(args)) | |
file_.write('\n') | |
return closure | |
def csv(filename): | |
""" | |
Append .csv to filename | |
""" | |
return '{0}.csv'.format(filename) | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1 | order_1 | |
---|---|---|
2 | order_2 | |
4 | order_4 | |
5 | order_5 | |
6 | order_6 | |
9 | order_9 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import merge | |
def test_basic_match(): | |
orders = reader(""" 1, order_1 """) | |
trades = reader(""" 1, 101, trade_101 """) | |
detail = Writer() | |
error = Writer() | |
merge.doit(orders, trades, detail, error) | |
assert detail.data == [('1', '101', 'order_1', 'trade_101')] | |
assert error.data == [] | |
def test_basic_error(): | |
orders = reader(""" 2, order_2 """) | |
trades = reader(""" 1, 101, trade_101 """) | |
detail = Writer() | |
error = Writer() | |
merge.doit(orders, trades, detail, error) | |
assert detail.data == [] | |
assert error.data == [('1', '101', 'trade_101')] | |
def test_zoltan(): | |
orders = reader(""" 5, order_5 """) | |
trades = reader(""" 1, 101, trade_101 | |
2, 102, trade_102 | |
5, 105, trade_105 """) | |
detail = Writer() | |
error = Writer() | |
merge.doit(orders, trades, detail, error) | |
assert detail.data == [('5', '105', 'order_5', 'trade_105')] | |
assert error.data == [('1', '101', 'trade_101'), | |
('2', '102', 'trade_102')] | |
def test_inner_while(): | |
orders = reader(""" 1, order_1 | |
2, order_2 | |
3, order_3 | |
4, order_4 """) | |
trades = reader(""" 4, 104, trade_104 """) | |
detail = Writer() | |
error = Writer() | |
merge.doit(orders, trades, detail, error) | |
assert detail.data == [('4', '104', 'order_4', 'trade_104')] | |
assert error.data == [] | |
def test_stop_iteration(): | |
orders = reader(""" 5, order_5 """) | |
trades = reader(""" 7, 107, trade_107 """) | |
detail = Writer() | |
error = Writer() | |
merge.doit(orders, trades, detail, error) | |
assert detail.data == [] | |
assert error.data == [('7', '107', 'trade_107')] | |
def test_from_file(): | |
orders = merge.reader('orders') | |
trades = merge.reader('trades') | |
detail = Writer() | |
error = Writer() | |
merge.doit(orders, trades, detail, error) | |
assert detail.data == [('4', '102', 'order_4', 'trade_102'), | |
('4', '103', 'order_4', 'trade_103'), | |
('5', '104', 'order_5', 'trade_104'), | |
('9', '106', 'order_9', 'trade_106')] | |
assert error.data == [('3', '101', 'trade_101'), | |
('7', '105', 'trade_105')] | |
class Writer(object): | |
""" | |
Helper writer class (mock) | |
""" | |
def __init__(self): | |
self.data = [] | |
def __call__(self, *data): | |
self.data.append(data) | |
def reader(string): | |
""" | |
Helper reader function | |
""" | |
for line in string.replace(' ', '').split('\n'): | |
yield line.split(',') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3 | 101 | trade_101 | |
---|---|---|---|
4 | 102 | trade_102 | |
4 | 103 | trade_103 | |
5 | 104 | trade_104 | |
7 | 105 | trade_105 | |
9 | 106 | trade_106 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment