diff --git a/Sources/OTCore/Extensions/Swift/Collections.swift b/Sources/OTCore/Extensions/Swift/Collections.swift index 5b7e732..60fcf55 100644 --- a/Sources/OTCore/Extensions/Swift/Collections.swift +++ b/Sources/OTCore/Extensions/Swift/Collections.swift @@ -812,6 +812,53 @@ extension Collection where Element : Hashable { } +// MARK: - shortest() / shortestIndex() + +extension Collection where Element: StringProtocol { + + /// **OTCore:** + /// Returns the shortest string in the collection. + /// If more than one element are the same length as the shortest element, the first will be returned. + /// - complexity: O(*n*) + @inlinable @_disfavoredOverload + public func shortest() -> Element? { + + guard let idx = shortestIndex() else { return nil } + return self[idx] + + } + + /// **OTCore:** + /// Returns the index of the shortest string in the collection. + /// If more than one element are the same length as the shortest element, the first will be returned. + /// - complexity: O(*n*) + @inlinable @_disfavoredOverload + public func shortestIndex() -> Index? { + + guard !isEmpty else { return nil } + + var shortestIndex: Index = startIndex + var shortestLength: Int = self[startIndex].count + + for index in indices { + let elementLength = self[index].count + if elementLength < shortestLength { + shortestIndex = index + shortestLength = elementLength + } + + // return early if empty string is encountered since + // there is no shorter string possible + if elementLength == 0 { + return shortestIndex + } + } + + return shortestIndex + + } +} + // MARK: - stringValueArrayLiteral extension Collection where Element: BinaryInteger { diff --git a/Tests/OTCoreTests/Extensions/Swift/Collections Tests.swift b/Tests/OTCoreTests/Extensions/Swift/Collections Tests.swift index 16ca4ee..20fbe82 100644 --- a/Tests/OTCoreTests/Extensions/Swift/Collections Tests.swift +++ b/Tests/OTCoreTests/Extensions/Swift/Collections Tests.swift @@ -1165,6 +1165,28 @@ class Extensions_Swift_Collections_Tests: XCTestCase { } + func testStringProtocol_Shortest() { + + XCTAssertEqual([String]().shortest(), nil) + XCTAssertEqual([""].shortest(), "") + XCTAssertEqual(["A"].shortest(), "A") + XCTAssertEqual(["abc", "A", "1", "xy", ""].shortest(), "") + XCTAssertEqual(["abc", "A", "1", "xy"].shortest(), "A") + XCTAssertEqual(["abc", "1", "A", "xy"].shortest(), "1") + + } + + func testStringProtocol_ShortestIndex() { + + XCTAssertEqual([String]().shortestIndex(), nil) + XCTAssertEqual([""].shortestIndex(), 0) + XCTAssertEqual(["A"].shortestIndex(), 0) + XCTAssertEqual(["abc", "A", "1", "xy", ""].shortestIndex(), 4) + XCTAssertEqual(["abc", "A", "1", "xy"].shortestIndex(), 1) + XCTAssertEqual(["abc", "1", "A", "xy"].shortestIndex(), 1) + + } + // MARK: - .stringValueArrayLiteral func teststringValueArrayLiteral() {