Skip to content

Commit

Permalink
Add mapping sum overload
Browse files Browse the repository at this point in the history
Motivation:

It is common to want a sum of values after applying a transform, but doing so with a map and sum is O(2n) while an implementation could be made for O(n).

Modifications:

- Add `sum(_:)` overload for inline transformations before summing.

Result:

Faster sums of transformations
  • Loading branch information
Mordil committed Jan 21, 2020
1 parent 71285fe commit b898bb4
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 5 deletions.
22 changes: 22 additions & 0 deletions Sources/Currency/AnyCurrency+Sequence.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

import Foundation

// MARK: Sum

extension Sequence where Element: AnyCurrency {
/// Returns the sum total of all amounts in the sequence.
///
Expand Down Expand Up @@ -51,4 +53,24 @@ extension Sequence where Element: AnyCurrency {
result += next
}
}

/// Returns the sum total of amounts in the sequence after applying the provided transform.
///
/// Rather than doing a `.map(_:)` and then `.sum()`, the `sum` result will be calculated inline while applying the transformations.
///
/// For example, you may want to calculate what the total taxes would be from a sequence of individual prices:
///
/// let prices: [USD] = [3.00, 2.99, 5.98]
/// // apply a 9% tax rate to each price and calculate the sum
/// let totalTaxes = prices.sum { $0 * Decimal(0.09) }
/// // totalTaxes == USD(1.08)
///
/// - Complexity: O(*n*), where *n* is the length of the sequence.
/// - Parameter transform: A mapping closure. `transform` accepts an element of this sequence as its parameter
/// and returns a transformed value of the same type.
/// - Returns: A currency value representing the sum total of all the transformed amounts in the sequence.
@inlinable
public func sum(_ transform: (Element) throws -> (Element)) rethrows -> Element {
return try self.reduce(into: .init(.zero)) { $0 += try transform($1) }
}
}
5 changes: 0 additions & 5 deletions Tests/CurrencyTests/AnyCurrencyTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -182,11 +182,6 @@ extension Sequence where Element: AnyCurrency {
func applyingRate(_ rate: Decimal) -> [Element] {
return self.reduce(into: [Element]()) { $0.append($1 + ($1 * rate)) }
}

func sum(_ transform: (Element) -> Element) -> Element {
return self.reduce(into: [Element](), { $0.append(transform($1)) })
.sum()
}
}

extension AnyCurrencyTests {
Expand Down

0 comments on commit b898bb4

Please sign in to comment.