Skip to content

Commit

Permalink
Add Set methods union, formUnion, intersection and `formInter…
Browse files Browse the repository at this point in the history
…section` that accept a cursor.
  • Loading branch information
groue committed Jun 5, 2024
1 parent bb789e3 commit bbbd6bb
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ GRDB adheres to [Semantic Versioning](https://semver.org/), with one exception:
## Next Release

- **New**: Added `QueryInterfaceRequest.deleteAndFetchIds(_:)` which returns the set of deleted ids.
- **New**: Added `Set` methods `union`, `formUnion`, `intersection` and `formIntersection` that accept a cursor.

## 6.27.0

Expand Down
50 changes: 50 additions & 0 deletions GRDB/Core/Cursor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,56 @@ extension Set {
// database cursors.
try cursor.forEach { insert($0) }
}

/// Returns a new set with the elements of both this set and the
/// given cursor.
///
/// If the set already contains one or more elements that are also in
/// the cursor, the existing members are kept. If the cursor contains
/// multiple instances of equivalent elements, only the first instance
/// is kept.
///
/// - parameter cursor: A cursor of elements.
/// - returns: A new set with the unique elements of this set
/// and `cursor`.
public func union(_ cursor: some Cursor<Element>) throws -> Set<Element> {
var result = self
try result.formUnion(cursor)
return result
}

/// Inserts the elements of the given cursor into the set.
///
/// If the set already contains one or more elements that are also in
/// the cursor, the existing members are kept. If the cursor contains
/// multiple instances of equivalent elements, only the first instance
/// is kept.
///
/// - parameter cursor: A cursor of elements.
public mutating func formUnion(_ cursor: some Cursor<Element>) throws {
while let element = try cursor.next() {
insert(element)
}
}

/// Returns a new set with the elements that are common to both this set
/// and the given cursor.
///
/// - parameter cursor: A cursor of elements.
/// - returns: A new set.
public func intersection(_ cursor: some Cursor<Element>) throws -> Set<Element> {
var result = self
try result.formIntersection(cursor)
return result
}

/// Removes the elements of the set that aren’t also in the
/// given cursor.
///
/// - parameter cursor: A cursor of elements.
public mutating func formIntersection(_ cursor: some Cursor<Element>) throws {
try formIntersection(Set(cursor))
}
}

extension Sequence {
Expand Down
26 changes: 26 additions & 0 deletions Tests/GRDBTests/CursorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,32 @@ class CursorTests: GRDBTestCase {
let set = try Set(cursor, minimumCapacity: 100)
XCTAssertEqual(set, [1, 2, 3])
}

do {
let cursor = AnyCursor([1, 2, 1, 3])
let set: Set<Int> = [1, 4]
try XCTAssertEqual(set.union(cursor), [1, 2, 3, 4])
}

do {
let cursor = AnyCursor([1, 2, 1, 3])
var set: Set<Int> = [1, 4]
try set.formUnion(cursor)
XCTAssertEqual(set, [1, 2, 3, 4])
}

do {
let cursor = AnyCursor([1, 2, 1, 3])
let set: Set<Int> = [1, 3, 4]
try XCTAssertEqual(set.intersection(cursor), [1, 3])
}

do {
let cursor = AnyCursor([1, 2, 1, 3])
var set: Set<Int> = [1, 3, 4]
try set.formIntersection(cursor)
XCTAssertEqual(set, [1, 3])
}
}

func testDictionaryGrouping() throws {
Expand Down

0 comments on commit bbbd6bb

Please sign in to comment.