Skip to content

Instantly share code, notes, and snippets.

@fxm90
Last active January 25, 2026 15:36
Show Gist options
  • Select an option

  • Save fxm90/be62335d987016c84d2f8b3731197c98 to your computer and use it in GitHub Desktop.

Select an option

Save fxm90/be62335d987016c84d2f8b3731197c98 to your computer and use it in GitHub Desktop.
Extension for a Combine-Publisher that returns the current and previous value.
//
// 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()
}
}
@joaquin102
Copy link

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