Swift: Banking on reduce()


Think of a bank statement with its opening balance, its transactions and its closing balance. Think likewise of a column in an excel spreadsheet where we tally a column, adding together all the amounts using sum(). In Swift, this type of addition is achieved using reduce(), where the opening balance is the initial value, and the output is our closing balance:
let openingBalance = 10.00
let transactions = [-5.54, 10.45, 6.57,-50.00]
let closingBalance = transactions.reduce(openingBalance, combine: {runningTotal, transactionValue in runningTotal + transactionValue})
closingBalance // -28.52
The combine closure is written out in long form here for clarity, but it could be abbreviated simply to a + sign:
let openingBalance = 10.00
let transactions = [-5.54, 10.45, 6.57,-50.00]
let closingBalance = transactions.reduce(openingBalance, combine: +)
closingBalance // -28.52
Equally we could imagine a debit and credits column on our statement:
let openingBalance = 10.10
let debits = [5.54, 10.45, 6.57, 50.00]
let credits = [5.54, 10.45, 6.57, 50.00]
let debitBalance = debits.reduce(openingBalance, combine: -)
let closingBalance = credits.reduce(debitBalance, combine: +) // 10.1
Or for some reason we might have an array nested with credit and debit subarrays,
let openingBalance = 10.00
let transactions = [[-5.54, -50.00],[10.45, 6.57]]
let closingBalance = transactions.flatMap{$0}.reduce(openingBalance, combine: +)
closingBalance // -28.52
and decide to employ our friend flatMap().

Journeys with maps

We could even go crazy and use a combination of separate arrays and (flat)mapping:
let openingBalance = 10.10
let debits = [5.54, 10.45, 6.57, 50.00]
let credits = [5.54, 10.45, 6.57, 50.00]
let closingBalance = [credits,debits.map{-$0}].flatMap{$0}.reduce(openingBalance, combine: +)
closingBalance // 10.1
Here an array is built that combines credit and debit arrays but maps debits to negative figures at the same time, before flatMapping and reducing!

Departing on a tangent

And since we've come this far, let's have some fun and throw in a sorted() function to work out the highest credit and highest debit.
let openingBalance = 10.10
let debits = [5.54, 10.45, 6.57, 50.00]
let credits = [5.54, 10.45, 6.57, 50.00]
let sortedAmounts = sorted([credits,debits.map{-$0}].flatMap{$0},>)
let highestCredit = sortedAmounts.first // 50
let highestDebit = sortedAmounts.last! < 0 ? -(sortedAmounts.last!) : 0 // 50
Now we're (flat)mapping, sorting and nil coalescing. Although, yes we've strayed from reduce() and so should return.

Further use of reduce(): String Arrays

Beyond numbers, reduce() can also be used with string arrays:
let words = ["Hello", " ", "Playgrounds", "!"]
let sentence = (words.reduce(""){sentence, newWord in sentence + newWord} )
sentence // "Hello Playgrounds!"
Here reconstructing a sentence from its constituent into parts. And we could imagine a similar scenario where an array of paragraphs is combined to return the full text (for searching, etc.).


Endorse on Coderwall

Comments