private/Resolve-WtwFuzzyMatch.ps1
|
function Resolve-WtwFuzzyMatch { <# .SYNOPSIS Finds the closest match for a name from a list of candidates using Levenshtein distance. .OUTPUTS PSCustomObject with: Match (string or $null), Suggestions (string[] if tied) #> [CmdletBinding()] param( [Parameter(Mandatory)][string] $Name, [Parameter(Mandatory)][string[]] $Candidates ) $maxDist = [Math]::Max(2, [Math]::Floor($Name.Length / 3)) $fuzzyMatches = @() foreach ($candidate in $Candidates) { $dist = Get-WtwEditDistance $Name $candidate if ($dist -le $maxDist) { $fuzzyMatches += [PSCustomObject]@{ Target = $candidate; Dist = $dist } } } $fuzzyMatches = $fuzzyMatches | Sort-Object Dist if ($fuzzyMatches.Count -eq 0) { return [PSCustomObject]@{ Match = $null; Suggestions = @() } } $best = $fuzzyMatches[0] $tied = @($fuzzyMatches | Where-Object { $_.Dist -eq $best.Dist }) if ($tied.Count -eq 1) { Write-Verbose "Fuzzy match: '$Name' -> '$($best.Target)'" return [PSCustomObject]@{ Match = $best.Target; Suggestions = @() } } return [PSCustomObject]@{ Match = $null; Suggestions = @($tied | ForEach-Object { $_.Target }) } } |