Forum Discussion
A generalisation of the MAP lambda helper function
- Sep 08, 2024
This is a demonstration of the proposed MAP function used to solve a challenge provided by Oz_Sunray and Wyn Hopkins on data cleansing and vote counting. The key element of my solution is to build a table of validated votes for each voter ID and each candidate (i.e. an array of arrays - much the same as any other problem of interest). The formula is modularised using Lambda functions. They are not that pretty, but neither are they impossible to follow.
"Worksheet formula" = AggregateVotesλ( tblVOTES[VoterID], tblVOTES[[Vote1]:[Vote3]], weight, tblAvailable[AVAILABLE] )
which calls
/* "FUNCTION NAME: AggregateVotesλ" "DESCRIPTION: Aggregates all votes to candidate colors" */ /* "REVISIONS: Date Developer Description" " 08 Sep 2024 Peter Bartholomew Original Development" */ AggregateVotesλ = LAMBDA(voterID, votesCast, weight, available, LET( person, TOROW(UNIQUE(voterID)), votes, MAPλ(person, AssignVotesλ(voterID, votesCast, weight, available)), count, HSTACK(available, BYROW(votes, SUM)), return, TAKE(SORT(count, 2, -1), 4), return ) );
to build and aggregate the table of votes. This, in turn, calls another Lambda function to clean and validate the votes corresponding to a single voterID
/* "FUNCTION NAME: AssignVotesλ" "DESCRIPTION: Validates and assigns votes to candidate colors for a single voterID " */ /* "REVISIONS: Date Developer Description" " 08 Sep 2024 Peter Bartholomew Original Development" */ AssignVotesλ = LAMBDA(voterID, ballots, weight, available, LAMBDA(p, LET( // "In the case of duplicate ballots return first" votesCast, XLOOKUP(p, voterID, ballots), // "Remove invalid and repeated votes" valid, COUNTIFS(available, votesCast), distinct, EXPAND(UNIQUE(FILTER(votesCast, valid), TRUE), , 3, ""), // "Assign votes to candidate colours" assigned, BYROW((distinct = available) * weight, SUM), assigned ) ) );
I took the problem from Wyn's recording
https://www.youtube.com/watch?v=FIcxyLqzWcE
Thanks for the preliminary feedback. You are correct; it would be a large and somewhat indigestible meal taken at one sitting! Its saving grace might be that it is possible to pick the small appetiser off the top without getting involved with anything too rich.
The Lambda helper function itself is intended to hide all its complexity from the user. I wrote it as a stop-gap until such time as Microsoft get their act together and write versions of their helper functions that will generate arrays of arrays rather than error messages. I understand Google Sheets does not have this limitation.
My idea in publishing the MAPλ helper function at this stage is to get others to try it. All that is required is to write a function that generates an array and then use MAP to specify a repeated structure that will fail with the nested array error. Then bring the MAPλ helper function into the AFE from GitHub and use IntelliSense autocomplete to select MAPλ in place of MAP. Everything should just work with no further effort on behalf of the user.
These days most of the formulas I write today generate arrays of arrays in order to make best use of the spreadsheet grid. Sometimes it is possible by using broadcasting but, as soon as a helper function is involved, things start to fall apart. REDUCE/_STACK offers an understandable solution for smaller problems but it runs out of control as the problem size increases.
If you to try the function, let me know how you get on. Did it deliver what you require and did it appear to be efficient?
- Patrick2788Sep 04, 2024Silver Contributor
I'm having fun with this function.
=LET( first, SEQUENCE(3, 3), second, SEQUENCE(10000, 12), MAPλ(first, LAMBDA(v, v * second)) )
For the amount of lifting I'm asking it to do the calculation speed is impressive. I'm using 32 bit Excel at work and the average speed of a fullcalc is about 1.9 seconds. Not bad at all!
- PeterBartholomew1Sep 04, 2024Silver Contributor
Pretty ambitious. To still be alive and kicking at 30,000 rows and over a million products is promising.