Last active
September 21, 2019 13:29
-
-
Save kristopherjohnson/635e56dcc71842502fcd to your computer and use it in GitHub Desktop.
Generic sum() and mean() extensions for Swift numeric collections
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// To use reduce() to sum a sequence, we need | |
/// | |
/// - a zero (identity) element | |
/// - an addition operator | |
protocol Summable { | |
/// Identity element for this type and the + operation. | |
static var Zero: Self { get } | |
/// + operator must be defined for this type | |
func +(lhs: Self, rhs: Self) -> Self | |
} | |
extension SequenceType where Generator.Element: Summable { | |
/// Return sum of all values in the sequence | |
func sum() -> Generator.Element { | |
return self.reduce(Generator.Element.Zero, combine: +) | |
} | |
} | |
// Define Zero for Int, Double, and String so we can sum() them. | |
// | |
// Extend this to any other types for which you want to use sum(). | |
extension Int: Summable { | |
/// The Int value 0 | |
static var Zero: Int { return 0 } | |
} | |
extension Double: Summable { | |
/// The Double value 0.0 | |
static var Zero: Double { return 0.0 } | |
} | |
extension String: Summable { | |
/// Empty string | |
static var Zero: String { return "" } | |
} | |
/// A generic mean() function requires that we be able | |
/// to convert values to Double. | |
protocol DoubleConvertible { | |
/// Return value as Double type | |
var doubleValue: Double { get } | |
} | |
// Define doubleValue() for Int and Double. | |
// | |
// Extend this to any other types for which you want | |
// to use mean(). | |
extension Int: DoubleConvertible { | |
/// Return Int as Double | |
var doubleValue: Double { return Double(self) } | |
} | |
extension Double: DoubleConvertible { | |
/// Return Double value | |
var doubleValue: Double { return self } | |
} | |
extension CollectionType where | |
Generator.Element: DoubleConvertible, | |
Generator.Element: Summable, | |
Index.Distance: DoubleConvertible { | |
/// Return arithmetic mean of values in collection | |
func mean() -> Double { | |
assert(!self.isEmpty, "cannot calculate mean of empty collection") | |
return self.sum().doubleValue / self.count.doubleValue | |
} | |
} | |
// Examples | |
[1, 2, 3, 4, 5].sum() // 15 | |
[1.1, 2.2, 3.3, 4.4, 5.5].sum() // 16.5 | |
["a", "b", "c", "d", "e"].sum() // "abcde" | |
[1, 2, 3, 5].mean() // 2.75 | |
[0.4, 1.2, 3.2].mean() // 1.6 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Awesome work man!