generic closure in the Collection protocol extension

Viewed 40

I need to write a method called count(where:) to all collections to count the number of elements that pass a provided test. There is one caveat I want be able to call it like this:

let workouts: [Exercise] = [ellipticalWorkout, runningWorkout]
let hardWorkoutCount = workouts.count(where: { $0.caloriesBurned >= 500})   // 1

protocol and structs declaration

protocol Exercise: CustomStringConvertible {
    var caloriesBurned: Double {get set}
    var minutes: Double {get set}
    var title: String {get}
}

struct ElipticalWorkout: Exercise {
    var caloriesBurned: Double
    var minutes: Double
}

struct RunningWorkout: Exercise {
    var caloriesBurned: Double
    var minutes: Double
    var meters: Double
}

let elipticalWorkout = ElipticalWorkout(caloriesBurned: 335, minutes: 30)
let runningWorkout = RunningWorkout(caloriesBurned: 650, minutes: 25, meters: 5000)

here is what I have tried so far: (those are just my first steps I think I need a generic type declaration in the method)

extension Collection {
    func count(where arrOfBools: () -> [Bool]) -> Int {
        // here i count the true values in the arrOfBool..
        let results = arrOfBools()
        var count = 0
        for element in results {
            if element == true {
                count += 1
            }
        }
        
        return count
    }
}
var arrExample = [400,200,600].count(where: {$0 >= 500}) // it returns a compile error
1 Answers

@Sweeper's answer is an excellent one and completely correct. I think it may also be worth mentioning that you can use filter and count to accomplish the same sorts of things without extending Collection:

var arrExample = [400,200,600].filter({ $0 > 500 }).count

or

let hardWorkoutCount = workouts.filter({$0.caloriesBurned >= 500}).count
Related