2016-11-04 5 views
0

Итак, я сделал свой ввод с чтения-хоста в массив, и решил, что он позволит мне подсчитать количество раз, когда слово в предложении $ a видно из $ Массив. Однако граф ++ не дает мне полнуюPowershell - Как я могу подсчитать количество совпадений в моем массиве

function Get-Sentence($a){ 
       if($a -contains $array) { 
        $Count++ 
       } 
      else { 
        return 0 
       } 
     } 
     Write-Host "There are $count words" 

     [array]$Array = @("a", "an", "the") 
     [array]$a = Read-Host "Enter a long sentence from a story book or novel: ").split(" ") 
+0

'-contains' не работает таким образом. Вы спрашиваете, содержит ли разбитый массив весь массив слов, который вы указали, что явно не имеет (в нем содержатся слова, а не массив). Вы можете решить это с помощью цикла или более эффективно, сохранив список слов в качестве хэш-таблицы и проверив членство в этом. –

+0

Спасибо за ваш быстрый ответ, так что вы говорите, что я должен сделать массив $ Array в хеш-таблицу? – SkullNerd

ответ

2

Предпочтительный подход:

Самый простой способ для точного подсчета вхождений нескольких подстрок, вероятно:

  1. Construct шаблон регулярное выражение, которое совпадает по любому из подстроки
  2. Используйте оператора -split, чтобы разделить строку
  3. Подсчитайте количество строк и вычесть 1:

# Define the substrings and a sentence to test against 
$Substrings = "a","an","the" 
$Sentence = "a long long sentence to test the -split approach, anticipating false positives" 

# Construct the regex pattern 
# The \b sequence ensures "word boundaries" on either side of a 
# match so that "a" wont match the a in "man" for example 
$Pattern = "\b(?:{0})\b" -f ($Substrings -join '|') 

# Split the string, count result and subtract 1 
$Count = ($Sentence -split $Pattern).Count - 1 

Выходы:

C:\> $Count 
2 

Как вы можете видеть, что это будет соответствовать и разделить на "а" и "", но не "ЭН" в «предвидя».

Я оставлю это преобразование в функцию упражнения для читателя


Примечание: , если начать кормить больше, чем просто простых ASCII строк в качестве входных данных, вы можете захотеть, чтобы избежать их, прежде чем используя их в схеме:

$Pattern = "\b(?:{0})\b" -f (($Substrings |ForEach-Object {[regex]::Escape($_)}) -join '|') 

наивный подход:

Если вам неудобно использовать регулярные выражения, вы можете сделать предположение, что что-либо между двумя пробелами является «словом» (например, в вашем исходном примере), а затем перебирайте слова в предложении и проверяйте, есть ли массив содержит слово в вопросе (не наоборот):

$Substrings = "a","an","the" 
$Sentence = (Read-Host "Enter a long sentence from a story book or novel: ").Split(" ") 

$Counter = 0 

foreach($Word in $Sentence){ 
    if($Substrings -contains $Word){ 
     $Counter++ 
    } 
} 

Как suggested by Jeroen Mostert, вы также можете использовать HashTable. При этом вы можете отслеживать вхождения каждого слова, а не просто общее количество:

$Substrings = "a","an","the" 
$Sentence = (Read-Host "Enter a long sentence from a story book or novel: ").Split(" ") 

# Create hashtable from substrings 
$Dictionary = @{} 
$Substrings |ForEach-Object { $Dictionary[$_] = 0 } 

foreach($Word in $Sentence){ 
    if($Dictionary.ContainsKey($Word)){ 
     $Dictionary[$Word]++ 
    } 
} 

$Dictionary 
+0

Благодарим за быстрый ответ! Я не понимаю, что происходит в части '' \ b (?: {0}) \ b "'. Есть ли способ, которым я мог бы использовать его, как мой сценарий написан? – SkullNerd

+0

@BartVanRooijen '\ b (?: sometext) \ b' - шаблон регулярного выражения - '{0}' является заполнителем. Оператор '-f' заменит' {0} 'первым аргументом в правой части. Когда вы говорите «используйте его так, как написано моим сценарием», что именно вы имеете в виду? Например, оператор '-contains' не имеет смысла в этом контексте –

+0

Большое вам спасибо! – SkullNerd

1
$Substrings = "a","an","the" 
    ("a long long sentence to test the -split approach, anticipating false positives" -split " " | where {$Substrings -contains $_}).Count 
Смежные вопросы