Last active
January 25, 2026 15:36
-
-
Save fxm90/be62335d987016c84d2f8b3731197c98 to your computer and use it in GitHub Desktop.
Extension for a Combine-Publisher that returns the current and previous value.
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
| // | |
| // Combine+Pairwise.swift | |
| // | |
| // Created by Felix Mau on 17.05.21. | |
| // Copyright © 2021 Felix Mau. All rights reserved. | |
| // | |
| import Combine | |
| extension Publisher { | |
| typealias Pairwise<T> = (previous: T?, current: T) | |
| /// Emits a tuple containing the previous and current elements from the upstream publisher. | |
| /// | |
| /// The first emitted tuple has `nil` as the `previous` value because there is no element | |
| /// before the first one. | |
| /// | |
| /// ### Example | |
| /// | |
| /// ```swift | |
| /// let subscription = (1...5).publisher | |
| /// .pairwise() | |
| /// .sink { print("(\($0.previous), \($0.current))", terminator: " ") } | |
| /// ``` | |
| /// | |
| /// Output: | |
| /// ``` | |
| /// (nil, 1) (Optional(1), 2) (Optional(2), 3) (Optional(3), 4) (Optional(4), 5) | |
| /// ``` | |
| /// | |
| /// - Returns: A type-erased publisher that emits `(previous, current)` tuples | |
| /// for each element produced by the upstream publisher. | |
| /// | |
| /// Based on: <https://stackoverflow.com/a/67133582/3532505> | |
| func pairwise() -> AnyPublisher<Pairwise<Output>, Failure> { | |
| // `scan` requires an initial value, which is `nil` in this case. | |
| // We therefore emit an optional tuple and remove the optional using `compactMap`. | |
| scan(nil) { previousPair, currentElement -> Pairwise<Output>? in | |
| Pairwise(previous: previousPair?.current, current: currentElement) | |
| } | |
| .compactMap { $0 } | |
| .eraseToAnyPublisher() | |
| } | |
| } |
Author
Amazing!! Thank you so much for this 🙌
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Related test when using XCTest
Related test when using Swift Testing