//
//  Sequence+Transformed.swift
//  Swiftest
//
//  Created by Brian Strobach on 12/12/18.
//

extension Sequence where Element: Sequence {
    public var flattened: [Self.Element.Element] {
        return flatMap {$0}
    }
}

extension Sequence {

    /// Swiftest: Reduces an array while returning each interim combination.
    ///
    ///     [1, 2, 3].accumulate(initial: 0, next: +) -> [1, 3, 6]
    ///
    /// - Parameters:
    ///   - initial: initial value.
    ///   - next: closure that combines the accumulating value and next element of the array.
    /// - Returns: an array of the final accumulated value and each interim combination.
    public func accumulate<U>(initial: U, next: (U, Element) throws -> U) rethrows -> [U] {
        var runningTotal = initial
        return try map { element in
            runningTotal = try next(runningTotal, element)
            return runningTotal
        }
    }
    
    /// Swiftest: Filtered and map in a single operation.
    ///
    ///     [1,2,3,4,5].filtered({ $0 % 2 == 0 }, map: { $0.string }) -> ["2", "4"]
    ///
    /// - Parameters:
    ///   - isIncluded: condition of inclusion to evaluate each element against.
    ///   - transform: transform element function to evaluate every element.
    /// - Returns: Return an filtered and mapped array.
    public func filtered<T>(_ isIncluded: ThrowingPredicate<Element>, map transform: (Element) throws -> T) rethrows ->  [T] {
        return try compactMap({
            if try isIncluded($0) {
                return try transform($0)
            }
            return nil
        })
    }
    
}
