Last active
February 2, 2018 01:28
-
-
Save chrislconover/ac344ec28c118f8e4a922795fbf59983 to your computer and use it in GitHub Desktop.
Diffing RxSwift observables
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
let v = Variable<[Int]>([1, 2, 3]) | |
let withDiffs = v.asObservable().withDiffs(startingWith: []) | |
.subscribe(onNext: { print("With diffs: \($0)") }) | |
let justDiffs = v.asObservable().diffs(startingWith: []) | |
.subscribe(onNext: { print("Just diffs: \($0)") }) | |
v.value = [1, 3, 4] | |
prints: | |
> Got diffs: ([1, 3, 4], [D(1), I(2,4)]) | |
> Just diffs: [D(1), I(2,4)] |
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
// Created by Chris Conover on 1/27/18. | |
import Differ | |
import RxSwift | |
extension ObservableType where E:Collection, E.Iterator.Element: Equatable { | |
func withDiffs(startingWith first: E) -> Observable<(E, [Patch<E.Element>])> { | |
return withPrevious(startWith: first) | |
.map { from, to in (to, from.diff(to).patch(from: from, to: to)) } | |
} | |
func diffs(startingWith first: E) -> Observable<([Patch<E.Element>])> { | |
return withDiffs(startingWith: first).map { $0.1 } | |
} | |
} | |
extension ObservableType where E:Collection, E.Iterator.Element: Equatable { | |
func withDiffs(startingWith first: E) -> Observable<(E, [Patch<E.Element>])> { | |
return withPrevious(startWith: first) | |
.map { from, to in (to, from.diff(to).patch(from: from, to: to)) } | |
} | |
} | |
public extension Diff { | |
/// Generates a patch sequence based on a diff. It is a list of steps to be applied to obtain the `to` collection from the `from` one. | |
/// | |
/// - Complexity: O(N) | |
/// | |
/// - Parameters: | |
/// - from: The source collection (usually the source collecetion of the callee) | |
/// - to: The target collection (usually the target collecetion of he callee) | |
/// - Returns: A sequence of steps to obtain `to` collection from the `from` one. | |
public func patch<T: Collection, U>(from: T, to: T, offset: Int, _ transform: (T.Element) -> U) | |
-> [Patch<U>] where T.Iterator.Element: Equatable { | |
return patch(from: from, to: to).map { $0.map(offset: offset, transform) } | |
} | |
} | |
public extension Patch { | |
public func map<U>(offset: Int, _ transform: (Element) -> U) -> Patch<U> { | |
switch self { | |
case let .insertion(index, element): | |
return .insertion(index: index + offset, element: transform(element)) | |
case let .deletion(index): | |
return .deletion(index: index + offset) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment