您应使用reduce
方法来按以下方式求和您的序列元素:
Xcode Xcode 10.2+ • Swift 5或更高级版本
extension Sequence where Element: AdditiveArithmetic {
func sum() -> Element { reduce(.zero, +) }
}
extension Collection where Element: BinaryInteger {
func average() -> Element { isEmpty ? .zero : sum() / Element(count) }
func average<T: FloatingPoint>() -> T { isEmpty ? .zero : T(sum()) / T(count) }
}
extension Collection where Element: BinaryFloatingPoint {
func average() -> Element { isEmpty ? .zero : sum() / Element(count) }
}
let votes = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let votesTotal = votes.sum()
let votesAverage = votes.average()
let votesDoubleAverage: Double = votes.average()
如果你需要使用 Decimal
类型并计算它们的总和,可以直接使用 AdditiveArithmetic
协议扩展方法实现,因此只需实现平均值即可:
extension Collection where Element == Decimal {
func average() -> Decimal { isEmpty ? .zero : sum() / Decimal(count) }
}
如果您需要对自定义结构的某个属性进行求和,可以扩展
Sequence
并创建一个接受KeyPath作为参数来计算其总和的方法:
extension Sequence {
func sum<T: AdditiveArithmetic>(_ predicate: (Element) -> T) -> T {
reduce(.zero) { $0 + predicate($1) }
}
}
使用方法:
struct User {
let name: String
let age: Int
}
let users: [User] = [
.init(name: "Steve", age: 45),
.init(name: "Tim", age: 50)]
let ageSum = users.sum(\.age)
将集合扩展以计算其平均值:
extension Collection {
func average<T: BinaryInteger>(_ predicate: (Element) -> T) -> T {
sum(predicate) / T(count)
}
func average<T: BinaryInteger, F: BinaryFloatingPoint>(_ predicate: (Element) -> T) -> F {
F(sum(predicate)) / F(count)
}
func average<T: BinaryFloatingPoint>(_ predicate: (Element) -> T) -> T {
sum(predicate) / T(count)
}
func average(_ predicate: (Element) -> Decimal) -> Decimal {
sum(predicate) / Decimal(count)
}
}
用法:
let ageAvg = users.average(\.age)
let ageAvgDouble: Double = users.average(\.age)