Самая длинная общая подстрока для более чем двух строк в PowerShell? - PullRequest
7 голосов
/ 20 ноября 2011

как найти соответствующие строки в массиве строк в PowerShell:

пример:

$Arr = "1 string first",
"2 string second",
"3 string third",
"4 string fourth"

Используя этот пример, я хочу, чтобы это возвращалось:

" string "

Я хочу использовать это, чтобы найти совпадающие части имен файлов, а затем удалить эту часть имени файла (например, удалить имя исполнителя из набора mp3-файлов), без необходимости указывать, какая часть имени файла следует заменить вручную.

Ответы [ 4 ]

6 голосов
/ 21 ноября 2011
$arr =  "qdfbsqds", "fbsqdt", "bsqda" 
$arr | %{

$substr = for ($s = 0; $s -lt $_.length; $s++) {
           for ($l = 1; $l -le ($_.length - $s); $l++) {
            $_.substring($s, $l);
           }
          } 
$substr | %{$_.toLower()} | select -unique

} | group | ?{$_.count -eq $arr.length} | sort {$_.name.length} | select -expand name -l 1
# returns bsqd
  • создать список всех уникальных подстрок входных строк
  • фильтр для подстрок, которые встречаются раз #inputstrings (т.е. во всех входных строках)
  • отсортировать эти отфильтрованные подстроки по длине подстроки
  • возвращает последний (т.е. самый длинный) из этого списка
1 голос
/ 20 ноября 2011

Если это (имя исполнителя и т. Д.) Будет только одним словом:

$Arr = "1 string first", "2 string second", "3 string third", "4 string fourth"
$common = $Arr | %{ $_.split() } | group | sort -property count | select -last 1 | select -expand name
$common = " {0} " -f $common

Обновление:

Реализация, которая, кажется, работает для нескольких слов (поиск самого длинного общегоподстрока слов):

$arr = "1 string a first", "2 string a second", "3 string a third", "4 string a fourth"
$common = $arr | %{
$words = $_.split()
$noOfWords = $words.length
for($i=0;$i -lt $noOfWords;$i++){
    for($j=$i;$j -lt $noOfWords;$j++){
        $words[$i..$j] -join " "
    }
}

} | group | sort -property count,name | select -last 1 | select -expand name

$common = " {0} " -f $common
$common
1 голос
/ 20 ноября 2011

Вот функция «Longest Common Substring» для двух строк в PowerShell (на основе викибук C # пример ):

Function get-LongestCommonSubstring
{
Param(
[string]$String1, 
[string]$String2
)
    if((!$String1) -or (!$String2)){Break}
    # .Net Two dimensional Array:
    $Num = New-Object 'object[,]' $String1.Length, $String2.Length
    [int]$maxlen = 0
    [int]$lastSubsBegin = 0
    $sequenceBuilder = New-Object -TypeName "System.Text.StringBuilder"

    for ([int]$i = 0; $i -lt $String1.Length; $i++)
    {
        for ([int]$j = 0; $j -lt $String2.Length; $j++)
        {
            if ($String1[$i] -ne $String2[$j])
            {
                    $Num[$i, $j] = 0
            }else{
                if (($i -eq 0) -or ($j -eq 0))
                {
                        $Num[$i, $j] = 1
                }else{
                        $Num[$i, $j] = 1 + $Num[($i - 1), ($j - 1)]
                }
                if ($Num[$i, $j] -gt $maxlen)
                {
                    $maxlen = $Num[$i, $j]
                    [int]$thisSubsBegin = $i - $Num[$i, $j] + 1
                    if($lastSubsBegin -eq $thisSubsBegin)
                    {#if the current LCS is the same as the last time this block ran
                            [void]$sequenceBuilder.Append($String1[$i]);
                    }else{ #this block resets the string builder if a different LCS is found
                        $lastSubsBegin = $thisSubsBegin
                        $sequenceBuilder.Length = 0 #clear it
                        [void]$sequenceBuilder.Append($String1.Substring($lastSubsBegin, (($i + 1) - $lastSubsBegin)))
                    }
                }
            }
        }
    }
    return $sequenceBuilder.ToString()
}

Чтобы использовать это для более чем двух строк, используйте это так:

Function get-LongestCommonSubstringArray
{
Param(
[Parameter(Position=0, Mandatory=$True)][Array]$Array
)
    $PreviousSubString = $Null
    $LongestCommonSubstring = $Null
    foreach($SubString in $Array)
    {
        if($LongestCommonSubstring)
        {
            $LongestCommonSubstring = get-LongestCommonSubstring $SubString $LongestCommonSubstring
            write-verbose "Consequtive diff: $LongestCommonSubstring"
        }else{
            if($PreviousSubString)
            {
                $LongestCommonSubstring = get-LongestCommonSubstring $SubString $PreviousSubString
                write-verbose "first one diff: $LongestCommonSubstring"
            }else{
                $PreviousSubString = $SubString
                write-verbose "No PreviousSubstring yet, setting it to: $PreviousSubString"
            }
        }
    }
    Return $LongestCommonSubstring
}


get-LongestCommonSubstringArray $Arr -verbose
0 голосов
/ 20 ноября 2011

Если я понимаю ваш вопрос:

$Arr = "1 string first", "2 string second", "3 string third", "4 string fourth"
$Arr -match " string " | foreach {$_ -replace " string ", " "}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...