Home > Blockchain >  Powershell. How to check that no string in array starts with some character?
Powershell. How to check that no string in array starts with some character?

Time:09-01

I already know how to check if a string in an array DOES start with some character:

foreach ($str in $arr) {
    if ($str.StartsWith("abc")) {
        do this
    }
}

But I need the code that will have somewhat different logic: "if no string in this array starts with abc, then do this"

Please help me to build code for that with the means of Powershell. I have no clue.

CodePudding user response:

Keeping the code you already have and showing a different alternative, you can loop through each element of the array and when the condition becomes true you can return $true and break your loop as no further comparison is needed:

$comparison = foreach ($str in $arr) {
    if ($str.StartsWith("abc")) {
        $true
        break
    }
}

if(-not $comparison) {
    # here is if no element of `$arr` starts with abc
}

CodePudding user response:

The -like comparison operator will act as a filter when you apply it to an array - making it easy to determine if any string in the array starts with abc:

if(@($arr) -like 'abc*'){
    # at least 1 string in $arr starts with abc
}

To get the opposite, use the -not operator:

if(-not(@($arr) -like 'abc*')){
    # no string in $arr starts with abc
}

CodePudding user response:

Using your example:

foreach ($str in $arr) {
    if (-not $str.StartsWith("abc")) {
        do this
    }
}

Or,

$Filter = @('abc', 'def', 'abcghj') | Where-Object { -not $_.startswith('a') }

Then you can iterate over $Filter

CodePudding user response:

Using member-access enumeration and this comparison operator feature:

When the input of an operator is a scalar value, the operator returns a Boolean value. When the input is a collection, the operator returns the elements of the collection that match the right-hand value of the expression. If there are no matches in the collection, comparison operators return an empty array. For example:

if (!($Arr.StartsWith("abc") -eq $True)) {
    'no string in $arr starts with abc'
}

If it concerns a very large array and you don't want to search further when any string starting with abc is already found (as the helpful suggestion from Santiago), you might also use the PowerShell Where method:

if (!($Arr.Where({ $_.StartsWith("abc") }, 'First'))) {
    'no string in $arr starts with abc'
}

Note that in comparison with PowerShell's native case sensitivity the .Net StartsWith method is case sensitive.

CodePudding user response:

This is not an answer, it is a performance test, and results, of the answers

This is the test code and results for the code examples provided by Mathias, iRon, and Santiago.

If anyone spots any errors, logic or otherwise, please let me know so I can correct it.

Setup for the test:

Defines the array and variables used in the test.

function Get-RandomAlphaNumericString{
    [OutputType([string])]
    param (
        [parameter(Mandatory = $false, Position = 0)]
        [ValidateScript({$_ -gt 0})]
        [int]$Length = 1
    )
    [char[]]$Chars = [char[]]::new($Length)
    for ($i = 0; $i -lt $Length; $i  ) {
        $Chars[$i] = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'[(Get-Random -Maximum 62)]
    }
    return [string]::new($Chars)
}
function Get-RandomAlphaNumericStrings{
    [OutputType([string[]])]
    param (
        [parameter(Mandatory = $false, Position = 0)]
        [ValidateScript({$_ -gt 0})]
        [int]$ArrayLength = 1,
        [parameter(Mandatory = $false, Position = 1)]
        [ValidateScript({$_ -gt 0})]
        [int]$StringLength = 1
    )
    [string[]]$Strings = [string[]]::new($ArrayLength)
    for ($i = 0; $i -lt $ArrayLength; $i  ) {
        $Strings[$i] = Get-RandomAlphaNumericString $StringLength
    }
    return $Strings
}
$ArraySize = 100000
$LoopCount = 100

$arr = Get-RandomAlphaNumericStrings $ArraySize 20
[int]$IdxAt10Percent = $arr.Length * 0.1
[int]$IdxAt50Percent = $arr.Length * 0.5
[int]$IdxAt90Percent = $arr.Length * 0.9
$At10PercentPrefix = $arr[$IdxAt10Percent].Substring(0, 3)
$At50PercentPrefix = $arr[$IdxAt50Percent].Substring(0, 3)
$At90PercentPrefix = $arr[$IdxAt90Percent].Substring(0, 3)
$IsMissingPrefix = '###'
$At10PercentLike = $At10PercentPrefix   '*'
$At50PercentLike = $At50PercentPrefix   '*'
$At90PercentLike = $At90PercentPrefix   '*'
$ThatIsMissingLike = $IsMissingPrefix   '*'

Mathias test code:

Write-Host "`nMathias:"
Write-Host "    Array of $ArraySize elements"
Write-Host "    Repeat for $LoopCount loops"
$NotFound = $false
Measure-Command {
    for ($i = 0; $i -lt $LoopCount; $i  ) {
        if(-not(@($arr) -like $At10PercentLike)){
            $NotFound = $true
        }
    }
} | ForEach-Object { Write-Host "Index Position = ${IdxAt10Percent}: { $($_.Seconds   $_.Milliseconds/1000) seconds }"}
$NotFound = $false
Measure-Command {
    for ($i = 0; $i -lt $LoopCount; $i  ) {
        if(-not(@($arr) -like $At50PercentLike)){
            $NotFound = $true
        }
    }
} | ForEach-Object { Write-Host "Index Position = ${IdxAt50Percent}: { $($_.Seconds   $_.Milliseconds/1000) seconds }"}
$NotFound = $false
Measure-Command {
    for ($i = 0; $i -lt $LoopCount; $i  ) {
        if(-not(@($arr) -like $At90PercentLike)){
            $NotFound = $true
        }
    }
} | ForEach-Object { Write-Host "Index Position = ${IdxAt90Percent}: { $($_.Seconds   $_.Milliseconds/1000) seconds }"}
$NotFound = $false
Measure-Command {
    for ($i = 0; $i -lt $LoopCount; $i  ) {
        if(-not(@($arr) -like $ThatIsMissingLike)){
            $NotFound = $true
        }
    }
} | ForEach-Object { Write-Host "Missing: { $($_.Seconds   $_.Milliseconds/1000) seconds }"}

iRon's test code:

Write-Host "`niRon:"
Write-Host "    Array of $ArraySize elements"
Write-Host "    Repeat for $LoopCount loops"
$NotFound = $false
Measure-Command {
    for ($i = 0; $i -lt $LoopCount; $i  ) {
        if (!($Arr.StartsWith($At10PercentPrefix) -eq $True)) {
            $NotFound = $true
        }
    }
} | ForEach-Object { Write-Host "Index Position = ${IdxAt10Percent}: { $($_.Seconds   $_.Milliseconds/1000) seconds }"}
$NotFound = $false
Measure-Command {
    for ($i = 0; $i -lt $LoopCount; $i  ) {
        if (!($Arr.StartsWith($At50PercentPrefix) -eq $True)) {
            $NotFound = $true
        }
    }
} | ForEach-Object { Write-Host "Index Position = ${IdxAt50Percent}: { $($_.Seconds   $_.Milliseconds/1000) seconds }"}
$NotFound = $false
Measure-Command {
    for ($i = 0; $i -lt $LoopCount; $i  ) {
        if (!($Arr.StartsWith($At90PercentPrefix) -eq $True)) {
            $NotFound = $true
        }
    }
} | ForEach-Object { Write-Host "Index Position = ${IdxAt90Percent}: { $($_.Seconds   $_.Milliseconds/1000) seconds }"}
$NotFound = $false
Measure-Command {
    for ($i = 0; $i -lt $LoopCount; $i  ) {
        if (!($Arr.StartsWith($IsMissingPrefix) -eq $True)) {
            $NotFound = $true
        }
    }
} | ForEach-Object { Write-Host "Missing: { $($_.Seconds   $_.Milliseconds/1000) seconds }"}

Santiago's test code:

Write-Host "`nSantiago:"
Write-Host "    Array of $ArraySize elements"
Write-Host "    Repeat for $LoopCount loops"
$NotFound = $false
Measure-Command {
    for ($i = 0; $i -lt $LoopCount; $i  ) {
        $comparison = foreach ($str in $arr) {
            if ($str.StartsWith($At10PercentPrefix)) {
                $true
                break
            }
        }
        if(-not $comparison) {
            $NotFound = $true
        }
    }
} | ForEach-Object { Write-Host "Index Position = ${IdxAt10Percent}: { $($_.Seconds   $_.Milliseconds/1000) seconds }"}
$NotFound = $false
Measure-Command {
    for ($i = 0; $i -lt $LoopCount; $i  ) {
        $comparison = foreach ($str in $arr) {
            if ($str.StartsWith($At50PercentPrefix)) {
                $true
                break
            }
        }
        if(-not $comparison) {
            $NotFound = $true
        }
    }
} | ForEach-Object { Write-Host "Index Position = ${IdxAt50Percent}: { $($_.Seconds   $_.Milliseconds/1000) seconds }"}
$NotFound = $false
Measure-Command {
    for ($i = 0; $i -lt $LoopCount; $i  ) {
        $comparison = foreach ($str in $arr) {
            if ($str.StartsWith($At90PercentPrefix)) {
                $true
                break
            }
        }
        if(-not $comparison) {
            $NotFound = $true
        }
    }
} | ForEach-Object { Write-Host "Index Position = ${IdxAt90Percent}: { $($_.Seconds   $_.Milliseconds/1000) seconds }"}
$NotFound = $false
Measure-Command {
    for ($i = 0; $i -lt $LoopCount; $i  ) {
        $comparison = foreach ($str in $arr) {
            if ($str.StartsWith($IsMissingPrefix)) {
                $true
                break
            }
        }
        if(-not $comparison) {
            $NotFound = $true
        }
    }
} | ForEach-Object { Write-Host "Missing: { $($_.Seconds   $_.Milliseconds/1000) seconds }"}

Typical PowerShell 5.1 results:

Mathias:
    Array of 100000 elements
    Repeat for 100 loops
Index Position = 10000: { 3.942 seconds }
Index Position = 50000: { 3.885 seconds }
Index Position = 90000: { 3.879 seconds }
Missing: { 3.878 seconds }

iRon:
    Array of 100000 elements
    Repeat for 100 loops
Index Position = 10000: { 17.431 seconds }
Index Position = 50000: { 17.449 seconds }
Index Position = 90000: { 17.47 seconds }
Missing: { 17.473 seconds }

Santiago:
    Array of 100000 elements
    Repeat for 100 loops
Index Position = 10000: { 1.118 seconds }
Index Position = 50000: { 5.461 seconds }
Index Position = 90000: { 9.859 seconds }
Missing: { 10.997 seconds }

Typical PowerShell Core 7.2.6 results:

Mathias:
    Array of 100000 elements
    Repeat for 100 loops
Index Position = 10000: { 1.082 seconds }
Index Position = 50000: { 1.08 seconds }
Index Position = 90000: { 1.077 seconds }
Missing: { 1.068 seconds }

iRon:
    Array of 100000 elements
    Repeat for 100 loops
Index Position = 10000: { 10.301 seconds }
Index Position = 50000: { 10.655 seconds }
Index Position = 90000: { 10.576 seconds }
Missing: { 10.633 seconds }

Santiago:
    Array of 100000 elements
    Repeat for 100 loops
Index Position = 10000: { 0.623 seconds }
Index Position = 50000: { 3.02 seconds }
Index Position = 90000: { 5.412 seconds }
Missing: { 5.984 seconds }
  • Related