1

I have an array with custom objects. Now what I need to do is when ever an element will be added or removed I need a method to be called where I'll compute totalCost. Is it possible??

class Company {
    var name: String?
    ....
    ....
    var employees[Employee] = []
    var totalCost: Float = 0
}

class Employee {
    var name: String?
    .....
    .....
    var salary: Float = 0
}

I have an option to override getter method of totalCost where I need go through all the employee object to calculate totalCost. But I don't want to do this cause I might have a huge number of employees and on every call this iteration can be a expensive operation.

Any suggestion will be appreciable.

Tapas Pal
  • 7,073
  • 8
  • 39
  • 86

3 Answers3

3

You can create a read-only computed property as follow:

class Employee {
    var name: String?
    var salary: Float = 0
    init(name: String, salary:Float) {
        self.name = name
        self.salary = salary
    }
}



class Company {
    var name: String?
    var employees:[Employee] = []
    var totalCost: Float  {
        return employees.map{$0.salary}.reduce(0){$0+$1}
    }
}


let employee1 = Employee(name: "Steve", salary: 5000)
let employee2 = Employee(name: "Chris", salary: 7000)
let employee3 = Employee(name: "John", salary: 3000)

let company = Company()
company.name = "ACME"
company.employees = [employee1,employee2,employee3]
company.totalCost   // 15000
Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
  • 1
    Thanks bro.. That was exactly what I looking for. – Tapas Pal Sep 03 '15 at 07:05
  • can you explain how : return employees.map{$0.salary}.reduce(0){$0+$1} works or point me to a site where this is explained. thx – Glenn Sep 03 '15 at 21:52
  • @Glenn map takes each employee salary from the array and returns an array of Float. reduce(0){$0+$1} means sum every element in the array and return its total – Leo Dabus Sep 04 '15 at 01:02
  • fwiw, the closure arguments can be inferred within `reduce`, i.e., `reduce(0, +)` – pxpgraphics Aug 29 '18 at 04:37
  • @pxpgraphics you are commenting on a 3 year old answer https://stackoverflow.com/questions/28288148/making-my-function-calculate-average-of-array-swift/28288619?s=1|59.2962#28288619 – Leo Dabus Aug 29 '18 at 04:43
  • @LeoDabus yes i was aware of that when i added the comment. i figured it would benefit others, who may find your answer helpful, to have a reference to the current Swift syntax. sorry for bothering you :] – pxpgraphics Aug 30 '18 at 05:38
0

You can make an extension to the Array class, where you override the append, insert, remove (atIndex),... and add the calculation method for the total.

Be sure however to override ALL methods that you use to add/remove (eg don't forget += if you use that!

Also take into account that if you change the salary of an Employee you also must calculate the totalCost (no array operations involved here so it won't trigger those methods).

You can make things much more efficient by not calculating ALL employees over and over again: eg append method : add the total of the new employee, remove method : in your override method first subtract before delete, setter method for salary: subtract old from total, add new to total... Again be careful because you can go wrong this way if you forget something!

Glenn
  • 2,808
  • 2
  • 24
  • 30
0

you can follow this approach in order to making an observer and notification:

in your array class do this:

let arrayChangedNotification = "myArrayDidChange"

class Company {
var name: String?
....
....
var employees: [Employee] = []{
didSet{
alertMe()
}
}
var totalCost: Float = 0

func alertMe() {
    let center = NSNotificationCenter.defaultCenter()
    center.postNotificationName(arrayChangedNotification, object: self)
}
}

and in your viewController add this:

func arrayDidChange(notification: NSNotification) {
 // whatever gonna happen in array change!
}

and in viewDidLoad() method add the observer to notification:

let center = NSNotificationCenter.defaultCenter()
    center.addObserver( self,
        selector: "arrayDidChange:",name: arrayChangedNotification,object: nil)
sbsr
  • 352
  • 3
  • 9