Posts: 9
Threads: 3
Joined: Dec 2020
Can anyone help explain how to make this snippet follow a more functional style? I was able to functionalize other portions of the code but having trouble with this.
def Report ():
data = Load ()
Report = ""
LastDate = GetDate (data[0])
Count = 0; Counts = [0,0,0,0,0,0,0,0,0,0]
for rec in data:
Count += 1
ThisDate = RecToDate (rec)
if ThisDate != LastDate:
Report += Summary (Count,Counts)
Count = 0; Counts = [0,0,0,0,0,0,0,0,0,0]
LastDate = ThisDate
for j in range (10): Counts[j] += RecRan (rec,j)
Report += str (rec)
return Report
Posts: 4,572
Threads: 71
Joined: Jan 2018
Dec-14-2020, 08:56 AM
(This post was last modified: Dec-14-2020, 08:56 AM by Gribouillis.
Edit Reason: improvement
)
I would try the following
from itertools import groupby
def report():
data = Load()
report = []
for date, irec in groupby(data, key=lambda r: RecToDate(r)):
irec = list(irec)
counts = [0] * 10
for rec in irec:
for j in range(10):
counts[j] += RecRan(rec, j)
report.append(str(rec))
report.append(Summary(len(irec), counts))
return ''.join(report)
Posts: 9
Threads: 3
Joined: Dec 2020
Thank you very much. I will study your suggestion. I wonder if there is a way to further reduce mutation and state.
Posts: 9
Threads: 3
Joined: Dec 2020
I tested your code and it worked with minor mods - nice work!
Posts: 4,572
Threads: 71
Joined: Jan 2018
Please post the modified code and we'll see if further reduction is possible.
Posts: 9
Threads: 3
Joined: Dec 2020
I wonder how to minimize loops and variables. Overall the code is still imperative.
def CountRuns (rec,counts):
for j in range(10): counts[j] += RecRan(rec, j)
def Report ():
data = Load ()
report = []
for date, irec in groupby(data, key=RecToDate):
irec = list(irec)
counts = [0] * 10
for rec in irec:
CountRuns (rec,counts)
report.append(StrRec(rec))
report.append(Summary(len(irec), counts, Strdate(date)))
return ''.join(report)
Posts: 4,572
Threads: 71
Joined: Jan 2018
Dec-15-2020, 05:45 PM
(This post was last modified: Dec-16-2020, 04:15 PM by Gribouillis.)
Here is my attempt in a non imperative style
import itertools as itt
import numpy as np
def count_incr(rec):
return np.array(RecRan(rec, j) for j in range(10))
def ireport_group(date, irec):
return itt.chain(
(StrRec(rec) for rec in irec),
(Summary(len(irec),
list(np.sum(count_incr(rec) for rec in irec)), Strdate(date)),))
def Report():
return ''.join(
itt.chain.from_iterable(
ireport_group(date, list(irec))
for date, irec in itt.groupby(Load(), key=RecToDate)))
Posts: 9
Threads: 3
Joined: Dec 2020
Thank you very much again - I'm impressed.
Unfortunately that takes me down what appears to be a huge rabbit hole with:
RuntimeError: The current Numpy installation ('C:\\Users\\Autologin\\AppData\\Local\\Programs\\Python\\Python39\\lib\\site-packages\\numpy\\__init__.py') fails to pass a sanity check due to a bug in the windows runtime. See: https://tinyurl.com/y3dm3h86
I'm not asking you to solve this also but maybe someone knows an easy fix off hand. My numpy install is new.
Posts: 4,572
Threads: 71
Joined: Jan 2018
Dec-15-2020, 08:42 PM
(This post was last modified: Dec-15-2020, 08:42 PM by Gribouillis.)
A quick fix is to not use numpy
from functools import reduce
import itertools as itt
ZERO = [0] * 10
def add_list(a, b):
return [x + y for x, y in zip(a, b)]
def count_incr(rec):
return [RecRan(rec, j) for j in range(10)]
def ireport_group(date, irec):
return itt.chain(
(StrRec(rec) for rec in irec),
(Summary(
len(irec),
reduce(add_list, (count_incr(rec) for rec in irec), ZERO),
Strdate(date)),))
def Report():
return ''.join(
itt.chain.from_iterable(
ireport_group(date, list(irec))
for date, irec in itt.groupby(Load(), key=RecToDate))) Another solution is probably to install numpy 1.19.3 as suggested in the dev page that you linked.
Posts: 1,822
Threads: 2
Joined: Apr 2017
NumPy really shouldn't be necessary to program in a functional style anyway.
I haven't really looked at the code much, so can't really provide many comments. You might like to look at the Toolz library that provides a lot of the kinds of functions you'd get in more mainstream functional languages.
|