diff --git a/Sources/SwiftDevKit/TextProcessing/String+Metrics.swift b/Sources/SwiftDevKit/TextProcessing/String+Metrics.swift deleted file mode 100644 index 1d8b64a..0000000 --- a/Sources/SwiftDevKit/TextProcessing/String+Metrics.swift +++ /dev/null @@ -1,223 +0,0 @@ -// String+Metrics.swift -// SwiftDevKit -// -// Copyright (c) 2025 owdax and The SwiftDevKit Contributors -// MIT License - https://opensource.org/licenses/MIT - -import Foundation - -public extension String { - /// Calculates the Levenshtein distance between this string and another string. - /// - /// The Levenshtein distance is the minimum number of single-character edits (insertions, deletions, or - /// substitutions) - /// required to change one string into another. - /// - /// Example: - /// ```swift - /// let distance = "kitten".levenshteinDistance(to: "sitting") // Returns 3 - /// ``` - /// - /// - Parameter other: The string to compare against - /// - Returns: The Levenshtein distance between the two strings - func levenshteinDistance(to other: String) -> Int { - let str1 = Array(self) - let str2 = Array(other) - let str1Length = str1.count - let str2Length = str2.count - - // Handle empty strings - if str1Length == 0 { return str2Length } - if str2Length == 0 { return str1Length } - - // Create matrix of size (str1Length+1)x(str2Length+1) - var matrix = Array(repeating: Array(repeating: 0, count: str2Length + 1), count: str1Length + 1) - - // Initialize first row and column - for i in 0...str1Length { - matrix[i][0] = i - } - for j in 0...str2Length { - matrix[0][j] = j - } - - // Fill in the rest of the matrix - for i in 1...str1Length { - for j in 1...str2Length { - if str1[i - 1] == str2[j - 1] { - matrix[i][j] = matrix[i - 1][j - 1] // No operation needed - } else { - matrix[i][j] = Swift.min( - matrix[i - 1][j] + 1, // deletion - matrix[i][j - 1] + 1, // insertion - matrix[i - 1][j - 1] + 1 // substitution - ) - } - } - } - - return matrix[str1Length][str2Length] - } - - /// Calculates the Jaro-Winkler distance between this string and another string. - /// - /// The Jaro-Winkler distance is a measure of similarity between two strings, with a higher score - /// indicating greater similarity (1.0 means the strings are identical, 0.0 means completely different). - /// It's particularly suited for short strings like names. - /// - /// Example: - /// ```swift - /// let similarity = "martha".jaroWinklerDistance(to: "marhta") // Returns ~0.961 - /// ``` - /// - /// - Parameters: - /// - other: The string to compare against - /// - scalingFactor: The scaling factor for how much the prefix affects the score (default: 0.1) - /// - Returns: A value between 0.0 and 1.0, where 1.0 means the strings are identical - func jaroWinklerDistance(to other: String, scalingFactor: Double = 0.1) -> Double { - let str1 = Array(self) - let str2 = Array(other) - let len1 = str1.count - let len2 = str2.count - - // If either string is empty, return 0 - if len1 == 0 || len2 == 0 { - return 0.0 - } - - // Maximum distance between two characters to be considered matching - let matchDistance = (Swift.max(len1, len2) / 2) - 1 - - // Arrays to keep track of matched characters - var matches1 = [Bool](repeating: false, count: len1) - var matches2 = [Bool](repeating: false, count: len2) - - // Count matching characters - var matchingChars = 0 - for i in 0.. 0 else { - return 0.0 - } - - // Count transpositions - var transpositions = 0 - var j = 0 - for i in 0.. Int { - guard count == other.count else { - throw StringMetricsError.unequalLength( - "Hamming distance requires strings of equal length: \(count) != \(other.count)") - } - - var distance = 0 - for i in 0..