Let the PowerShell Challenges Begin

string playThe Chairman has decided that it is in the best interests of his Iron Scripters, and those that wish to attain that valued designation, that training continue year-round. To that end, he has commissioned a series of PowerShell challenges. These challenges will range in complexity and be tagged accordingly. Although, you are encouraged to try your hand at all posted challenges. Some solutions may require complex coding, perhaps a PowerShell function. Others might be no more than a line or two of PowerShell that you would type interactively in the console. You are encouraged to share your work in social media, blogs, or sites like GitHub. You are welcome to post links to your work in comments to each challenge. Shall we begin?

For your first challenge exercise, consider these two arrays of strings.

$target = "Spooler", "Spork Client", "WinRM", "Spork Agent Service", "BITS","WSearch"
$list   = "winrm", "foo", "spooler", "spor*", "bar"

Your goal is to find the values in $List that do not match anything in $Target. Your code will be successful if you get foo and bar for results. This exercise is classified with an Intermediate level.

Good Luck and check back later for a suggested solution.


30 Replies to “Let the PowerShell Challenges Begin”

  1. Ionut Nica

    It is the first time I am participating in such a challenge, hope I got it right, here’s my attempt at the code:

    $res = @()
    foreach ($item in $list) {
    if (-not ($target -match $item)) {
    $res +=$item
    }
    }
    Write-Output $res

  2. John Steele

    I struggled finding a way to exclude ‘spor*’ from the output. I feel like I cheated by adding the second where() that specifically excludes words with a ‘*’.

    Two formats below:

    $list.Where({$_ -notin $target}).Where({$_ -notmatch ‘\*’})
    $list | Where-Object {$_ -notin $target} | Where-Object {$_ -notmatch ‘\*’}

  3. Michael Gustavsson

    My contribution 🙂
    $list | ForEach-Object { if (-not($target -like $_)) { Write-Output $_ } }

  4. Michael Scarn

    foreach ($i in $List) {
    If ($Target -like $i) {
    echo $null
    } Else {
    Write-Host -NoNewline “$i ”
    }
    }

  5. Manoj

    Hi this my output
    $result = @()
    foreach ($i in $list) {

    $a = @()
    $a += foreach ($j in $target) {
    $j -like $i
    }
    if ($a -notcontains $true) {
    $result += $i
    }

    }
    After seeing others comments damn there are lot of easier ways to do

  6. thedavecarroll

    I originally went down the path of $List.Where({$_ -notin $Target}) but, as mentioned by John above, this does not filter out the “spor*” list item which has two matches in $Target.

    One solution, builds an object array that contains the $List item and their corresponding $Target matches. The $MatchedListItems will clearly show what list item has no matches.

    “`
    $MatchedListItems = $List | ForEach-Object {
    [PSCustomObject]@{
    ListItem = $_
    TargetMatches = $Target -match $_
    }
    }
    $MatchedListItems.Where({-Not $_.TargetMatches}).ListItem

    $MatchedListItems

    ListItem TargetMatches
    ——– ————-
    winrm {WinRM}
    foo {}
    spooler {Spooler}
    spor* {Spooler, Spork Client, Spork Agent Service}
    bar {}
    “`

    At first, I was baffled as to why Spooler was matched by “spor*”, but a check on https://regex101.com/r/vQhwTv/1 shows that the ‘*’ is greedy. At least, that’s the best I can determine. Perhaps, Jeff could provide insight into this?

    This $MatchedListItems solution can then be simplified into the following succinct solution:

    “`
    $List.Where({-Not ($Target -match $_)})
    “`

  7. Michell Grauwmans

    $list | ? {!($target -match $_)} (shortest i can think of)
    I was thinking $list | where {$_ -notin $target} at first but that does not qualify match..
    Ramesh his answer is best, i just made it a bit shorter.

  8. Dawid_G

    Solution 1:

    $target = “Spooler”, “Spork Client”, “WinRM”, “Spork Agent Service”, “BITS”,”WSearch”
    $list = “winrm”, “foo”, “spooler”, “spor*”, “bar”

    $Result=@()

    $list | ForEach-Object {if (!($target -like $_)){$Result += $_}}

    Write-Output $Result

    Solution 2:

    $target = “Spooler”, “Spork Client”, “WinRM”, “Spork Agent Service”, “BITS”,”WSearch”
    $list = “winrm”, “foo”, “spooler”, “spor*”, “bar”

    $Result=@()

    foreach ($Element in $List)
    {
    if (!($target -like $Element))
    {
    $Result += $Element
    }
    }

    Write-Output $Result

  9. Greg M

    function Compare-Lists($target, $item) {

    [System.Collections.ArrayList]$NoMatchArray = $list

    foreach ($listItem in $list) {
    foreach ($targetItem in $target) {
    if ($targetItem -like $listItem) {
    $NoMatchArray.Remove($listItem)
    break
    }
    }
    }

    return $NoMatchArray
    }

  10. Samiksha Juneja

    foreach($listitem in $list)
    {
    $flag=0;
    for($i=0;$i -le $target.Count ;$i++)

    {
    if($target[$i] -like $listitem)
    {
    $flag=1
    }
    }

    if($flag -eq 0)
    {
    $listitem
    }
    }

  11. Yak

    You can do it in two ways:

    1) Compare-Object -ReferenceObject $list -DifferenceObject $target

    or

    2) $list | Where-Object { -not ($target -like $_) }

Comments are closed.