UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

SOLVED: Creating a function that finds the sum of elements between two arrays, adding only the corresponding elements (first + first, second + second, etc.)

Forums > Swift

Purpose of project: allow an employee to calculate/project future 401k yearly balances based on several future promotions. With promotions come pay raises.

Current challenge to overcome: create a function that finds the sum of each year's roth and traditional 401k balances. If the employee's roth 401k balance array were [$1000, $2000, $3000] and his traditional 401k balance array were [$100, $200, $300] (each element representing a year), the resulting combined balances array would be [$1100, $2200, $3300].

The entire code (version 0.2.0) is found on GitHub here.

Here are the sections that relate to the roth and traditional balance arrays which are found following the calc401k() function:

func balanceOfRoth() -> [Decimal] {
        //chunk the employmentHistory into years (i.e., 12-month groups
        let years = employmentHistory.chunked(into: 12)

        //start with an empty array of how much the employee
        //  puts into their Roth account each year
        var averageRothContribution: [Decimal] = []

        for (index, months) in years.enumerated() {
            //for one year, how much was contributed by the employee
            //  to their Roth account?
            let yearToRoth: Decimal = months.reduce(0) { runningTotal, dept in
                //what is the payRate for this month given a department
                //  and a number of years worked?
                let payRate = dept.payRate(forYearsWorked: index + 1)

                //calculate how much was put into the Roth account
                //  this month
                let monthlyToRoth = Calculations.computeMonthly401kDeposits(
                    hours: monthlyHoursWorked,
                    atPayRate: payRate,
                    percentTo401k: percentToRoth
                )

                //add the monthly Roth amount to the amounts for the
                //  rest of the amounts in this year
                return runningTotal + monthlyToRoth
            }

            //add the average of this year's amounts to the array of other year average amounts
            averageRothContribution.append(yearToRoth / Decimal(months.count))
        }

        //averageRothContribution now contains the average amount
        //  in each year that the employee contributed

        //start with an empty array of the balance in the
        //  employee's Roth account on a yearly basis
        var rothBalances: [Decimal] = []

        for idx in averageRothContribution.indices {
            //our principal will either be existingBalance (for the first item)
            //  or the previous item (for items 2...n)
            let principal = idx == 0
            ? existing401kbalance
            : rothBalances[idx - 1]

            //calculate the yearly balance
            let balance401k = calc401k(principal: principal,
                                       deposits: averageRothContribution[idx],
                                       rateOfReturn: Decimal(marketReturnRate)
            )

            //and add it to our list of balances
            rothBalances.append(balance401k)
        }

        //give it back to the caller
        return rothBalances
    }
    func balanceOfTrad() -> [Decimal] {
        //chunk the employmentHistory into years (i.e., 12-month groups
        let years = employmentHistory.chunked(into: 12)

        //start with an empty array of how much the employee
        //  puts into their Trad account each year
        var averageTradContribution: [Decimal] = []

        for (index, months) in years.enumerated() {
            //for one year, how much was contributed by the employee
            //  to their Trad account?
            let yearToTrad: Decimal = months.reduce(0) { runningTotal, dept in
                //what is the payRate for this month given a department
                //  and a number of years worked?
                let payRate = dept.payRate(forYearsWorked: index + 1)

                //calculate how much was put into the Trad account
                //  this month
                let monthlyToTrad = Calculations.computeMonthly401kDeposits(
                    hours: monthlyHoursWorked,
                    atPayRate: payRate,
                    percentTo401k: percentToTrad
                )

                //add the monthly Trad amount to the amounts for the
                //  rest of the amounts in this year
                return runningTotal + monthlyToTrad
            }

            //add the average of this year's amounts to the array of other year average amounts
            averageTradContribution.append(yearToTrad / Decimal(months.count))
        }

        //averageRothContribution now contains the average amount
        //  in each year that the employee contributed

        //start with an empty array of the balance in the
        //  employee's Roth account on a yearly basis
        var tradBalances: [Decimal] = []

        for idx in averageTradContribution.indices {
            //our principal will either be existingBalance (for the first item)
            //  or the previous item (for items 2...n)
            let principal = idx == 0
            ? existing401kbalance
            : tradBalances[idx - 1]

            //calculate the yearly balance
            let balance401k = calc401k(principal: principal,
                                       deposits: averageTradContribution[idx],
                                       rateOfReturn: Decimal(marketReturnRate)
            )

            //and add it to our list of balances
            tradBalances.append(balance401k)
        }

        //give it back to the caller
        return tradBalances
    }

Currently the balanceOfRoth() and balanceOfTrad() are separate functions. Each contains an array (rothBalances: [Decimal] & tradBalances: [Decimal]) I would like to create a function that finds of the sum of the elements between the arrays. First element of rothBalances + first element of tradBalances to find total 401k balance for that given year. And so on for each successive year/element.

Here is a clunky way of potentially finding a solution:

func balanceOfCombined() -> [Decimal] {
        //chunk the employmentHistory into years (i.e., 12-month groups
        let years = employmentHistory.chunked(into: 12)

        //start with an empty array of how much the employee
        //  puts into their Trad account each year
        var averageTradContribution: [Decimal] = []

        for (index, months) in years.enumerated() {
            //for one year, how much was contributed by the employee
            //  to their Trad account?
            let yearToTrad: Decimal = months.reduce(0) { runningTotal, dept in
                //what is the payRate for this month given a department
                //  and a number of years worked?
                let payRate = dept.payRate(forYearsWorked: index + 1)

                //calculate how much was put into the Trad account
                //  this month
                let monthlyToTrad = Calculations.computeMonthly401kDeposits(
                    hours: monthlyHoursWorked,
                    atPayRate: payRate,
                    percentTo401k: percentToTrad
                )

                //add the monthly Trad amount to the amounts for the
                //  rest of the amounts in this year
                return runningTotal + monthlyToTrad
            }

            //add the average of this year's amounts to the array of other year average amounts
            averageTradContribution.append(yearToTrad / Decimal(months.count))
        }

        //averageRothContribution now contains the average amount
        //  in each year that the employee contributed

        //start with an empty array of the balance in the
        //  employee's Roth account on a yearly basis
        var tradBalances: [Decimal] = []

        for idx in averageTradContribution.indices {
            //our principal will either be existingBalance (for the first item)
            //  or the previous item (for items 2...n)
            let principal = idx == 0
            ? existing401kbalance
            : tradBalances[idx - 1]

            //calculate the yearly balance
            let balance401k = calc401k(principal: principal,
                                       deposits: averageTradContribution[idx],
                                       rateOfReturn: Decimal(marketReturnRate)
            )

            //and add it to our list of balances
            tradBalances.append(balance401k)
        }

        //give it back to the caller
        return tradBalances

        var averageRothContribution: [Decimal] = []

        for (index, months) in years.enumerated() {
            //for one year, how much was contributed by the employee
            //  to their Roth account?
            let yearToRoth: Decimal = months.reduce(0) { runningTotal, dept in
                //what is the payRate for this month given a department
                //  and a number of years worked?
                let payRate = dept.payRate(forYearsWorked: index + 1)

                //calculate how much was put into the Roth account
                //  this month
                let monthlyToRoth = Calculations.computeMonthly401kDeposits(
                    hours: monthlyHoursWorked,
                    atPayRate: payRate,
                    percentTo401k: percentToRoth
                )

                //add the monthly Roth amount to the amounts for the
                //  rest of the amounts in this year
                return runningTotal + monthlyToRoth
            }

            //add the average of this year's amounts to the array of other year average amounts
            averageRothContribution.append(yearToRoth / Decimal(months.count))
        }

        //averageRothContribution now contains the average amount
        //  in each year that the employee contributed

        //start with an empty array of the balance in the
        //  employee's Roth account on a yearly basis
        var rothBalances: [Decimal] = []

        for idx in averageRothContribution.indices {
            //our principal will either be existingBalance (for the first item)
            //  or the previous item (for items 2...n)
            let principal = idx == 0
            ? existing401kbalance
            : rothBalances[idx - 1]

            //calculate the yearly balance
            let balance401k = calc401k(principal: principal,
                                       deposits: averageRothContribution[idx],
                                       rateOfReturn: Decimal(marketReturnRate)
            )

            //and add it to our list of balances
            rothBalances.append(balance401k)
        }

        //give it back to the caller
        return rothBalances

        var combinedBalances: [Decimal] = []  
        // somehow append the sum of each element of both roth and trad arrays into this combinedBalances array
    }

What I did above was simply combine the trad and roth balance functions so that the tradBalances and rothBalances would be accessible within one function. But I'm not sure how to loop through those two arrays to find the sum of individual corresponding elements.

The current print is:

Roth 401k Balance Year 3: 3115.20396231420428012956723300993944886
Trad 401k Balance Year 3: 4321.4984992379485032529639916373900652

Roth 401k Balance Year 4: 5853.9955987608963897745354300607654945
Trad 401k Balance Year 4: 8634.1583811920981350630169897649985946
(and so on...)

The combinedBalances function should be a simple sum of roth and trad. The combined balance for year three should be 7,436.69 (3315.20 + 4321.49). And year four should be 14,488.14 (5853.99 + 8634.15).

2      

You can use something like this to combine the two balances arrays:

func balanceOfCombined() -> [Decimal] {
    let rothBalances = balanceOfRoth()
    let tradBalances = balanceOfTrad()

    let combinedBalances = Array(zip(rothBalances, tradBalances)).map { $0.0 + $0.1 }
    return combinedBalances
}

2      

@roosterboy

That's a beautifully simple solution! Thank you!

Can you explain the "$0.0 + $0.1" portion?

2      

If you don't supply named parameters to a map closure (which we don't here), you can instead use anonymous parameters labeled as $0, $1, etc inside the closure.

Array(zip(rothBalances, tradBalances)) returns an array of tuples made from the elements of the two input arrays.

You refer to the first, second, etc members of an unlabeled tuple using .0, .1, etc.

So put that all together and this:

$0.0 + $0.1

means to add together the first and second members of the tuple passed into your map closure as anonymous parameter $0. We are taking an array of 2-tuples (i.e., a tuple with 2 members) with each member being a Decimal and summing the members of each tuple to generate an array of single Decimal values.

To show that in a closure signature (which you can write out for the map but usually isn't necessary:

((Decimal, Decimal)) -> Decimal

Make sense?

3      

@roosterboy

That makes sense, thank you!

2      

Hacking with Swift is sponsored by Essential Developer

SPONSORED Join a FREE crash course for mid/senior iOS devs who want to achieve an expert level of technical and practical skills – it’s the fast track to being a complete senior developer! Hurry up because it'll be available only until April 28th.

Click to save your free spot now

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.