Finding sum of elements in Swift array
Swift3 has changed to :
let multiples = [...]
sum = multiples.reduce(0, +)
Swift 3+ one liner to sum properties of objects
var totalSum = scaleData.map({$0.points}).reduce(0, +)
Where points is the property in my custom object scaleData that I am trying to reduce
This is the easiest/shortest method I can find.
Swift 3 and Swift 4:
let multiples = [...]
let sum = multiples.reduce(0, +)
print("Sum of Array is : ", sum)
Swift 2:
let multiples = [...]
sum = multiples.reduce(0, combine: +)
Some more info:
This uses Array's reduce method (documentation here), which allows you to "reduce a collection of elements down to a single value by recursively applying the provided closure". We give it 0 as the initial value, and then, essentially, the closure { $0 + $1 }
. Of course, we can simplify that to a single plus sign, because that's how Swift rolls.
In Swift 4 You can also constrain the sequence elements to Numeric protocol to return the sum of all elements in the sequence as follow
extension Sequence where Element: Numeric {
/// Returns the sum of all elements in the collection
func sum() -> Element { return reduce(0, +) }
}
edit/update:
Xcode 10.2 • Swift 5 or later
We can simply constrain the sequence elements to the new AdditiveArithmetic protocol to return the sum of all elements in the collection
extension Sequence where Element: AdditiveArithmetic {
func sum() -> Element {
return reduce(.zero, +)
}
}
Xcode 11 • Swift 5.1 or later
extension Sequence where Element: AdditiveArithmetic {
func sum() -> Element { reduce(.zero, +) }
}
let numbers = [1,2,3]
numbers.sum() // 6
let doubles = [1.5, 2.7, 3.0]
doubles.sum() // 7.2
To sum a property of a custom object we can extend Sequence to take a predicate to return a value that conforms to AdditiveArithmetic
:
extension Sequence {
func sum<T: AdditiveArithmetic>(_ predicate: (Element) -> T) -> T { reduce(.zero) { $0 + predicate($1) } }
}
Usage:
struct Product {
let id: String
let price: Decimal
}
let products: [Product] = [.init(id: "abc", price: 21.9),
.init(id: "xyz", price: 19.7),
.init(id: "jkl", price: 2.9)
]
products.sum(\.price) // 44.5