Сокращение произвольных подстрок немного сложнее, чем сопоставление префиксов, поскольку мы больше не можем полагаться на сортировку по алфавиту.
Вместо этого вы можете отсортировать по длина , а затем отслеживать паттерны, которые не могут быть удовлетворены более коротким, используя набор ha sh:
function Reduce-Wildcard
{
param(
[string[]]$Strings,
[switch]$SkipSort
)
# Create set containing all patterns, removes all duplicates
$Patterns = [System.Collections.Generic.HashSet[string]]::new($Strings, [StringComparer]::CurrentCultureIgnoreCase)
# Now that we only have unique terms, sort them by length
$Strings = $Patterns |Sort-Object -Property Length
# Start from the shortest possible pattern
for ($i = 0; $i -lt ($Strings.Count - 1); $i++) {
$current = $Strings[$i]
if(-not $Patterns.Contains($current)){
# Check that we haven't eliminated current string already
continue
}
# There's no reason to search for this substring
# in any of the shorter strings
$j = $i + 1
do {
$next = $Strings[$j]
if($Patterns.Contains($next)){
# Do we have a substring match?
if($next -like "*$current*"){
# Eliminate the superstring
[void]$Patterns.Remove($next)
}
}
$j++
} while ($j -lt $Strings.Count)
}
# Return the substrings we have left
return $Patterns
}
Затем используйте как:
$strings = [IO.File]::ReadLines('C:\Temp\Words.txt')
$reducedSet = Reduce-Wildcard -Strings $strings
Теперь это определенно не самый экономичный способ сокращения ваших шаблонов, но хорошая новость заключается в том, что вы можете легко разделить-и-завоевать большой набор входных данных путем объединения и сокращения промежуточных результатов:
Reduce-Wildcard @(
Reduce-Wildcard -Strings @('App','Apple')
Reduce-Wildcard -Strings @('Sword', 'Words')
Reduce-Wildcard -Strings @('Swords', 'Word')
)
Или, в случае нескольких файлов, вы можете связать последовательные сокращения следующим образом:
$patterns = @()
Get-ChildItem dictionaries\*.txt |ForEach-Object {
$patterns = Reduce-Wildcard -String @(
$_ |Get-Content
$patterns
)
}