## SOLVED: Is .map the right method for this task? Using .map to manipulate elements in array, operating within given constraints (projected pay raise of X% every Y years)

 Mar '23 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: Manipulate pay rates based on projected pay rate percentage increases at regular intervals. Example: A company has communicated to its employees an intention to increase all pay rates by 4% every four years initiated on every January 1st. Within the below arrays for pay rates, each element of the array represents a yearly pay raise. All employees climb the pay rate scale one element every year. The employee/app user will be able to toggle (Bool) on/off this option of regularly interval increases: var regularPayRateIncreases: Bool var regularPayRateIncreasePercentage: Double var regularPayRateIncreaseYearInterval: Int ... var charlotte = Employee("Charlotte Grote", birthdate: birthdate, hiredate: hiredate, retirementAge: 65, department: .other("Hospitality"), monthlyHoursWorked: 160, regularPayRateIncreases: true, regularPayRateIncreasePercentage: 4.0, regularPayRateIncreaseYearInterval: 4) The full code is found here on GitHub. However, I am able to fit the entire macOS Line Command Tool code here... import Foundation enum Calculations { private static let pennyRoundingBehavior = NSDecimalNumberHandler( roundingMode: .bankers, scale: 2, raiseOnExactness: false, raiseOnOverflow: true, raiseOnUnderflow: true, raiseOnDivideByZero: true ) static func computeMonthlyEarnings(hours hoursWorked: Int, atPayRate payRate: Int) -> Decimal { let base = Decimal(hoursWorked * payRate) as NSDecimalNumber return base.rounding(accordingToBehavior: pennyRoundingBehavior) as Decimal } } extension Array { func chunked(into size: Int) -> [[Element]] { return stride(from: 0, to: count, by: size).map { Array(self[\$0 ..< Swift.min(\$0 + size, count)]) } } } enum Department: RawRepresentable { case sales case management case seniorManagement case other(String) init?(rawValue: String) { switch rawValue { case "Sales": self = .sales case "Management": self = .management case "Senior Management": self = .seniorManagement case let dept: self = .other(dept) } } var rawValue: String { switch self { case .sales: return "Sales" case .management: return "Management" case .seniorManagement: return "Senior Management" case .other(let dept): return dept } } func payRate(forYearsWorked numberOfYears: Int) -> Int { let rates: [Int] switch self { case .sales: rates = [20,22,24,26,28,30,32,34,36,38,40] case .management: rates = [30,32,34,36,38,40,42,44,46,48,50] case .seniorManagement: rates = [40,42,44,46,48,50,52,54,56,58,60] default: rates = [10,12,14,16,18,20,22,24,26,28,30] } return rates[min(numberOfYears, rates.count) - 1] } } struct Employee { let name: String var birthdate: Date var hiredate: Date var retirementAge: Int var department: Department var monthlyHoursWorked: Int var regularPayRateIncreases: Bool var regularPayRateIncreasePercentage: Double var regularPayRateIncreaseYearInterval: Int private(set) var employmentHistory: [Department] init(_ name: String, birthdate: Date, hiredate: Date, retirementAge: Int, department: Department = .other("Employee"), monthlyHoursWorked: Int, regularPayRateIncreases: Bool, regularPayRateIncreasePercentage: Double, regularPayRateIncreaseYearInterval: Int) { self.name = name self.birthdate = birthdate self.hiredate = hiredate self.retirementAge = retirementAge self.department = department self.monthlyHoursWorked = monthlyHoursWorked self.regularPayRateIncreases = regularPayRateIncreases self.regularPayRateIncreasePercentage = regularPayRateIncreasePercentage self.regularPayRateIncreaseYearInterval = regularPayRateIncreaseYearInterval self.employmentHistory = [] } } extension Employee { mutating func promote(to newDepartment: Department) { department = newDepartment } mutating func work(months: Int) { employmentHistory .append(contentsOf: Array.init(repeating: department, count: months)) } mutating func work(years: Int) { work(months: years * 12) } mutating func work(years: Int, months: Int) { work(months: years * 12 + months) } func yearlyEarnings() -> [Decimal] { let years = employmentHistory.chunked(into: 12) var earnings: [Decimal] = [] for (index, months) in years.enumerated() { let yearEarnings: Decimal = months.reduce(0) { runningTotal, dept in let payRate = dept.payRate(forYearsWorked: index + 1) let monthlyEarnings = Calculations.computeMonthlyEarnings( hours: monthlyHoursWorked, atPayRate: payRate ) return runningTotal + monthlyEarnings } earnings.append(yearEarnings) } return earnings } } extension Employee { func yearlyDepartments() -> [String] { let years = employmentHistory.chunked(into: 12) let departments: [String] = years.map { months in var seenDepts: Set = [] return months.reduce(into: [String]()) { acc, dept in if seenDepts.insert(dept.rawValue).inserted { acc.append(dept.rawValue) } }.joined(separator: ",") } return departments } func yearlyDepartmentsEarnings() -> [(String, Decimal)] { let yearlyDepartments = yearlyDepartments() let yearlyEarnings = yearlyEarnings() let yearlyDepartmentsEarnings: [(departments: String, earnings: Decimal)] = Array(zip(yearlyDepartments, yearlyEarnings)) return yearlyDepartmentsEarnings } } var birthdate = DateComponents(calendar: .current, year: 1965, month: 7, day: 20).date! var hiredate = DateComponents(calendar: .current, year: 2021, month: 12, day: 28).date! var promotion1date = DateComponents(calendar: .current, year: 2023, month: 12, day: 28).date! var firstDeptMonths: Int { Calendar.current.dateComponents([.month], from: hiredate, to: promotion1date).month! } var promotion2date = DateComponents(calendar: .current, year: 2025, month: 6, day: 28).date! var secondDeptMonths: Int { Calendar.current.dateComponents([.month], from: promotion1date, to: promotion2date).month! } var promotion3date = DateComponents(calendar: .current, year: 2026, month: 12, day: 28).date! var thirdDeptMonths: Int { Calendar.current.dateComponents([.month], from: promotion2date, to: promotion3date).month! } var retireAge = 65 let retireDate = Calendar.current.date(byAdding: .year, value: retireAge, to: birthdate)! var fourthDeptMonths: Int { Calendar.current.dateComponents([.month], from: promotion3date, to: retireDate).month! } extension Date { var age: Int { Calendar.current.dateComponents([.year], from: self, to: Date()).year! } var yearGroup: Int { Calendar.current.dateComponents([.year], from: self, to: Date()).year! + 1} var totalYearsRemaining: Int { Calendar.current.dateComponents([.year], from: self, to: retireDate).year! } var totalMonthsRemaining: Int { Calendar.current.dateComponents([.month], from: self, to: retireDate).month! } } //age of employee let age = birthdate.age //number of years employee has worked for the company let yearGroup = hiredate.yearGroup func printYearlyDepartmentsAndEarnings(_ yearlyDeptsAndEarnings: [(departments: String, earnings: Decimal)]) { for (year, deptsAndEarnings) in yearlyDeptsAndEarnings.enumerated() { print("Department(s) for Year \(year + yearGroup + 1): \(deptsAndEarnings.departments)") print("Earnings for Year \(year + yearGroup + 1): \(deptsAndEarnings.earnings)") print("Age: \(year + age)") print("") } } var charlotte = Employee("Charlotte Grote", birthdate: birthdate, hiredate: hiredate, retirementAge: 65, department: .other("Hospitality"), monthlyHoursWorked: 160, regularPayRateIncreases: true, regularPayRateIncreasePercentage: 4.0, regularPayRateIncreaseYearInterval: 4) //give our employee some work history //months in Hospitality charlotte.work(months: firstDeptMonths) //ohh, a promotion! charlotte.promote(to: .sales) //months in Sales charlotte.work(months: secondDeptMonths) //another promotion. way to go, Charlotte! charlotte.promote(to: .management) //months in Management charlotte.work(months: thirdDeptMonths) //another promotion. way to go, Charlotte! charlotte.promote(to: .seniorManagement) //months in Senior Management charlotte.work(months: fourthDeptMonths) printYearlyDepartmentsAndEarnings(charlotte.yearlyDepartmentsEarnings()) In simple cases of array manipulation, the map method is a tried and true tool... let salesPayRate: [Double] = [20,22,24,26,28,30,32,34,36,38,40] var increasedPayRate = salesPayRate.map { (rate) -> Double in return rate * 1.04 } However, the above salesPayRate.map example does not allow for multiple manipulations at regular intervals (like multiplying by 1.04 every four years / every four elements until retirement). And since the last element of the payRate arrays will be the Charlotte's stagnated pay rate for several years until retirement, if an employee worked enough years to reach the end of the pay scale I need that last pay rate to continue to increase by 4% every four years until retirement. Is the map method the best tool for this more complex task? 3 Mar '23 I have reorganized the GitHub repository. It should be much clearer now: "1.1.0 (Use This One)" is the code referenced above. The current print using a Command Line Tool project is as follows: Department(s) for Year 3: Hospitality Earnings for Year 3: 19200 Age: 57 Department(s) for Year 4: Hospitality Earnings for Year 4: 23040 Age: 58 Department(s) for Year 5: Sales Earnings for Year 5: 46080 Age: 59 Department(s) for Year 6: Sales,Management Earnings for Year 6: 59520 Age: 60 Department(s) for Year 7: Management Earnings for Year 7: 72960 Age: 61 Department(s) for Year 8: Senior Management Earnings for Year 8: 96000 Age: 62 Department(s) for Year 9: Senior Management Earnings for Year 9: 99840 Age: 63 Department(s) for Year 10: Senior Management Earnings for Year 10: 103680 Age: 64 I appreciate any guidance you can provide to incorporate a regular pay raise function using a .map method or some other device. Thank you! 2 Mar '23 Hi, The only way i could think of is if the years until retirement is larger than the pay rate scale then append the last number X ammount of times. let yearsUntilRetirement = 16 let repeatingCount = yearsUntilRetirement - salesPayRate.count if repeatingCount > 0 { salesPayRate.append(contentsOf:(Array(repeating: salesPayRate[salesPayRate.count - 1], count: repeatingCount))) } and to multiply every 4th element of the array using .map i would use an index. var index = 1 var increasedPayRate = salesPayRate.map { (rate) -> Double in if index.isMultiple(of: 4) { index += 1 return rate * 1.04 } else { index += 1 return rate } } So the hole thing would look like this: var salesPayRate: [Double] = [20,22,24,26,28,30,32,34,36,38,40] let yearsUntilRetirement = 16 let repeatingCount = yearsUntilRetirement - salesPayRate.count if repeatingCount > 0 { salesPayRate.append(contentsOf:(Array(repeating: salesPayRate[salesPayRate.count - 1], count: repeatingCount))) } var index = 1 var increasedPayRate = salesPayRate.map { (rate) -> Double in if index.isMultiple(of: 4) { index += 1 return rate * 1.04 } else { index += 1 return rate } } Hopefully that's what your looking for. 2 Mar '23 @Hectorcrdna Thank you! This is a step in the right direction but there is major problem. The pay raise is only applied to the 4th, 8th, 12th, etc. The pay raise needs set a new standard. Meaning the 4% pay raise does not only apply to the 4th year but also all the years following. When we put your code in the Playground, it transforms the array from: [20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 40, 40, 40, 40, 40] to: [20, 22, 24, 27.04, 28, 30, 32, 35.36, 36, 38, 40, 41.6, 40, 40, 40, 41.6] Notice how the fifth element is 28 in both arrays. The fifth element should be 28 1.04. The sixth element should be 30 1.04. The eighth element should be 34 1.04 1.04. 2 Mar '23 Ok, i think i understand, try with this one. var salesPayRate: [Double] = [20,22,24,26,28,30,32,34,36,38,40] let yearsUntilRetirement = 16 let repeatingCount = yearsUntilRetirement - salesPayRate.count if repeatingCount > 0 { salesPayRate.append(contentsOf:(Array(repeating: salesPayRate[salesPayRate.count - 1], count: repeatingCount))) } var index = 1 var payRaise = 0 var increasedPayRate = salesPayRate.map { (rate) -> Double in if index.isMultiple(of: 4) { index += 1 payRaise += 1 var newRate = rate for _ in 0.. [Double] { var payRate: [Double] = [20,22,24,26,28,30,32,34,36,38,40] // Replace this with department's pay rate. let repeatingCount = yearsUntilRetirement - payRate.count if repeatingCount > 0 { payRate.append(contentsOf:(Array(repeating: payRate[payRate.count - 1], count: repeatingCount))) } var index = 1 var payRaise = 0 var increasedPayRate = payRate.map { (rate) -> Double in if index.isMultiple(of: yearInterval) { payRaise += 1 } index += 1 var newRate = rate for _ in 0..

SPONSORED Get accurate app localizations in minutes using AI. Choose your languages & receive translations for 40+ markets!

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.

You are not logged in