Reputation: 57
So I made my input from the read-host into an array an figured it would let me count the amount of times a word in the sentence $a is seen from the $Array. however Count++ doesn't give me a total
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(" ")
Upvotes: 0
Views: 3471
Reputation: 1
$mystring = "abc,123"
$elements = ($element = $mystring -split ",").count
Write-Host($elements)
2
Write-Host($element[0])
abc
Write-Host($element[1))
123
Upvotes: 0
Reputation: 60145
Another way to do it using Enumerable.Count
, a Hashset<T>
for efficiently check if each token is contained in the substrings and -split
to trim the white space from the split tokens.
$Substrings = [System.Collections.Generic.HashSet[string]]::new(
[string[]] ('a', 'an', 'the'),
[System.StringComparer]::InvariantCultureIgnoreCase)
$Sentence = Read-Host 'Enter a long sentence from a story book or novel: '
[System.Linq.Enumerable]::Count(
-split $Sentence,
[Func[string, bool]] { $Substrings.Contains($args[0]) })
Upvotes: 0
Reputation: 174545
Easiest way to accurately count occurrences of multiple substrings is probably:
-split
operator to split the string# 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
Outputs:
C:\> $Count
2
As you can see it will have matched and split on "a" and "the", but not the "an" in "anticipating".
I'll leave converting this into a function an exercise to the reader
Note: if you start feeding more than just simple ASCII strings as input, you may want to escape them before using them in the pattern:
$Pattern = "\b(?:{0})\b" -f (($Substrings |ForEach-Object {[regex]::Escape($_)}) -join '|')
If you're uncomfortable with regular expressions, you can make the assumption that anything in between two spaces is "a word" (like in your original example), and then loop through the words in the sentence and check if the array contains the word in question (not the other way around):
$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++
}
}
As suggested by Jeroen Mostert, you could also utilize a HashTable. With this you could track occurrences of each word, instead of just a total count:
$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
Upvotes: 2
Reputation: 17472
$Substrings = "a","an","the"
("a long long sentence to test the -split approach, anticipating false positives" -split " " | where {$Substrings -contains $_}).Count
Upvotes: 1