Skip to content

Instantly share code, notes, and snippets.

@3kwa
Last active December 19, 2015 00:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 3kwa/5868197 to your computer and use it in GitHub Desktop.
Save 3kwa/5868197 to your computer and use it in GitHub Desktop.
No standard library allowed exercise :S
__pycache__
details.csv
errors.csv
*.pyc
"""
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()
1 order_1
2 order_2
4 order_4
5 order_5
6 order_6
9 order_9
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(',')
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