Tag Archives: hash table

Remove a Hash Table from an Array of Hash Tables

Take a look at this post’s title. I got that as a question, from a coworker yesterday. I didn’t know the answer right away, but I took some time last night and a half hour or so today to put it to bed. As of now, I am able to remove a hash table from an array of hash tables. Ugh.

The below array is the one you get when you don’t cast the variable. That’s to say the $x variable doesn’t need [System.Array] in front of it. It effectively does nothing different to that variable. The problem with this type of array is that it’s partially immutable. We can’t remove values from the array.

[System.Array]$x = 'one','two','three'

Therefore, we either need to create a new array to hold the hash tables we still want (as we are removing one of them), or cast our array as [System.Collections.ArrayList]. A variable cast as such allows us to remove values from it.

[System.Collections.ArrayList]$y = 'four','five','six'

Use this next information as a key, or legend, for the further below code. The entire code can be copied into the ISE, or Visual Studio Code, and run.

1. Removes the user-defined variables used in the below code.
2. Creates three hash tables that each include a User key, a Number key, and a Color key.
3. Prompts user to enter 1 or 2 whether they want to use the same array, or a new one.*

* The same array indicates we’re casting our variable as [System.Collections.ArrayList] and using the same variable. The new array indicates we’re casting a new variable as [System.Array], which again is the default and doesn’t actually require a cast.

4. Creates an array of hash tables based on the value 1 or 2.
5. Displays the current array of hash tables (before any changes).
6. Loops through the values in the array and uses the same array (if 1 was chosen), or creates a new array (if 2 was chosen).
7. Displays the updated array of hash tables (removes the hash table that includes the User “bsmith”).

#1 Remove variables (not using function/function scope).
Clear-Host
Remove-Variable -Name Hash1,Hash2,Hash3,Option,HashtableArray,i,HashtableArrayNew -ErrorAction SilentlyContinue 

#2 Create hash tables.
$Hash1 = @{User = 'landrews';Number = 1;Color = 'Red'}
$Hash2 = @{User = 'bsmith';Number = 2; Color = 'Blue'}
$Hash3 = @{User = 'sjackson';Number = 3;Color = 'Yellow'}

#3 Set SameArray vs. NewArray.
Write-Output -InputObject 'This function is hard coded to remove the hash table that include "bsmith" from an array.'
Do {
    $Option = Read-Host -Prompt 'Press 1 to use the same array, or 2 to create a new array'
} Until ($Option -eq 1 -or $Option -eq 2)

#4 Create array of hash tables.
Switch ($Option) {
    '1' {[System.Collections.ArrayList]$HashtableArray = $Hash1,$Hash2,$Hash3; break}
    '2' {[System.Array]$HashtableArray = $Hash1,$Hash2,$Hash3}
}

#5 Display unmodified hash table.
###################################
$HashtableArray
"'''''''^ Array of hash tables bfore ^''''''"
"'''''''v Array of hash tables after v''''''"
###################################

#6 Loop through array of hash tables.
For ($i = 0; $i -le $HashtableArray.Count - 1; $i++) {
    Switch ($Option) {
        '1' {
            If ($HashtableArray[$i].Values -contains 'bsmith') {
                $HashtableArray.Remove($HashtableArray[$i])
            }
        }
        '2' {
            If (-Not($HashtableArray[$i].Values -contains 'bsmith')) {
                [System.Array]$HashtableArrayNew += $HashtableArray[$i]
            }
        }
    }
}

#7 Display updated array.
Switch ($Option) {
    '1' {$HashtableArray}
    '2' {$HashtableArrayNew}
}

The below results show the exact same thing when run either by entering 1 or 2. The difference is the variable that’s displayed. You can see the above variable that’s returned based on 1 or 2. If it’s 1, we display the $HashtableArray variable (the one we created initially). If it’s 2, we display the $HashtableArrayNew variable. That’s the one we create, since we can’t modify the existing $HashtableArray variable when it’s cast as [System.Array].

This function is hard coded to remove the hash table that includes "bsmith" from an array.
Press 1 to use the same array, or 2 to create a new array: 2

Name                           Value
----                           -----
Color                          Red
Number                         1
User                           landrews
Color                          Blue
Number                         2
User                           bsmith
Color                          Yellow
Number                         3
User                           sjackson
'''''''^ Array of hash tables bfore ^''''''
'''''''v Array of hash tables after v''''''
Color                          Red
Number                         1
User                           landrews
Color                          Yellow
Number                         3
User                           sjackson

And with that, I’m done here. Fun stuff. Mostly.

PSMonday #6: Monday, June 6, 2016

Topic: Splatting and Hash Tables Continued

Notice: This post is a part of the PowerShell Monday series — a group of quick and easy to read mini lessons that briefly cover beginning and intermediate PowerShell topics. As a PowerShell enthusiast, this seemed like a beneficial way to ensure those around me at work were consistently learning new things about Windows PowerShell. At some point, I decided I would share these posts here, as well. Here’s the PowerShell Monday Table of Contents.

So, back to splatting: If you ever have a parameter that doesn’t need an assigned value, where the value is equal to true if the parameter is included, and false if it’s not — a switch parameter — then use $true or $false as the parameter value in the hash table. You can see an example of this below. Notice that in the example one of the parameter values wasn’t hardcoded, and instead was assigned using the value from another variable. Doing this isn’t always necessary, but it’s being shown, as an example for a time when it may be needed.

$Command = 'Get-ADUser'
$Params = @{
    Name = $Command
    ShowWindow = $true
}

Get-Help @Params

It should be said, that if you don’t include a switch parameter in the hash table, that it won’t be included when the cmdlet is run, and will therefore be false by default.

Let’s splat Send-MailMessage. This command, and its need for so many parameters and parameter values, makes it a great candidate for splatting, unlike the above Get-Help command where there was only two included parameters.

$MailParams = @{
    From = 'noreply@mydomain.domain.com'
    To = 'tommymaynard@mydomain.domain.com'
    Subject = 'Using Send-MailMessage and Splatting'
    Body = "This email sent from $env:USERNAME."
    SmtpServer = 'smtp.mydomain.domain.edu'
}

Send-MailMessage @MailParams

Bonus: If you have more parameters to add to a command, and they’re not included in the hash table (for whatever reason), you can still add them to the command.

Send-MailMessage @MailParams -Attachments 'C:\file.txt'

Second Bonus: What could be done instead of adding a separate parameter and parameter value to the command, as we saw in the above Bonus section, is adding another key-value pair to our hash table using the .Add() method.

$MailParams.Add('Attachments','C:\File.txt')

$MailParams

Name              Value
----              -----
Attachments       C:\File.txt
SmtpServer        smtp.mydomain.domain.com
Subject           Using Send-MailMessage and Splatting
Body              This email sent from tommymaynard.
From              noreply@mydomain.domain.com
To                tommymaynard@mydomain.domain.com

Send-MailMessage @MailParams

That’s it. Enjoy your Monday.

Give a Parameter a Default Value (Part II)

Part I: http://tommymaynard.com/quick-learn-give-a-parameter-a-default-value-2015
Part III: http://tommymaynard.com/quick-learn-give-a-parameter-a-default-value-part-iii-2016

An old co-worker and friend contacted me last week. We hadn’t chatted since the last time I was interviewing for a job — a job I have now (well, pretty close anyway). I remember telling him I wanted a job that allowed me to work with Windows PowerShell. While he probably wasn’t surprised to hear this job did just that, he might have been, to hear I had started this site — a site using my name, and all about PowerShell. It’s a pretty serious commitment to associate your name with a technology, and continue to provide new content.

He mentioned to me that he wasn’t aware of the $PSDefaultParameterValues preference variable until he read this post. No joke, but it’s exciting to know that something I wrote was helpful for him. You see, this isn’t your average intelligence IT Pro, no, this is walking, talking IT genius. You know the kind — one of the ones you’d hire first, if you opened your own consulting business. In fact, during that same first chat, I discovered that he spoke at the Microsoft Higher-Education Conference in October 2014. He’s definitely doing something right.

As last weekend passed, I occasionally thought about that $PSDefaultParameterValues post and decided I should add something more to it, especially since I highlighted what I would consider to be the less used approach for populating this variable. First off, for those that haven’t read the previous post, the $PSDefaultParameterValues variable allows you to specify a default value for a cmdlet’s, or function’s, parameter(s).

For example, if I wanted the Get-Help cmdlet to always include the -ShowWindow parameter, then I can add that default value to the cmdlet like so:

PS C:\> $PSDefaultParameterValues
PS C:\> # Proof the variable is empty.
PS C:\> $PSDefaultParameterValues.Add('Get-Help:ShowWindow',$true)
PS C:\> $PSDefaultParameterValues

Name                           Value
----                           -----
Get-Help:ShowWindow            True

With this value set, every time we use the Get-Help cmdlet, it will include the -ShowWindow parameter, even though I don’t specifically enter it at the time the command is run. In the previous example, we use the .Add() method to add a key-value pair; however, I suspect that most people will actually be more likely to use a hash table to add the cmdlet and parameter, and its new, default parameter value. Here’s the same example as above using the hash table option.

PS C:\> $PSDefaultParameterValue
PS C:\> # Proof the variable is empty.
PS C:\> $PSDefaultParameterValues = @{'Get-Help:ShowWindow' = $true}
PS C:\> $PSDefaultParameterValues

Name                           Value
----                           -----
Get-Help:ShowWindow            True

Now for the reason I led with with .Add() method: If you use the hash table option above, and the variable is already populated, then it’s going to overwrite the value it’s already storing, unless we use the += assignment operator. Follow along in the next few examples under the assumption that $PSDefaultParameterValues, is already populated from the previous example.

PS C:\> $PSDefaultParameterValues

Name                           Value
----                           -----
Get-Help:ShowWindow            True

PS C:\> $PSDefaultParameterValues = @{'Get-ADUser:Server' = 'MyClosestDC'}
PS C:\> $PSDefaultParameterValues

Name                           Value
----                           -----
Get-ADUser:Server              MyClosestDC

In the example above, using the = assignment operator overwrote our Get-Help ShowWindow key-value pair, as it would with any populated variable. The idea here is that we either need to assign all the parameter default values at once (when using a hash table), or use the += assignment operator to append other key-value pairs. Here’s both ways:

PS C:\> $PSDefaultParameterValues
PS C:\> # Proof the variable is empty.
PS C:\> $PSDefaultParameterValues = @{'Get-Help:ShowWindow' = $true;'Get-ADUser:Server' = 'MyClosestDC'}
PS C:\> $PSDefaultParameterValues

Name                           Value
----                           -----
Get-ADUser:Server              MyClosestDC
Get-Help:ShowWindow            True

PS C:\> $PSDefaultParameterValues = $null
PS C:\> $PSDefaultParameterValues
PS C:\> # Proof the variable is empty.
PS C:\> $PSDefaultParameterValues = @{'Get-Help:ShowWindow' = $true}
PS C:\> $PSDefaultParameterValues += @{'Get-ADUser:Server' = 'MyClosestDC'}
PS C:\> $PSDefaultParameterValues

Name                           Value
----                           -----
Get-ADUser:Server              MyClosestDC
Get-Help:ShowWindow            True

That’s all there is to it. If you’re going to use a hash table and assign values to your $PSDefaultParameterValues at different times, then be sure to use the correct assignment operator, or use the .Add() method — it’s up to you. For me, I populate this variable in my profile, so overwriting it, is something in which I’m not concerned. Thanks for reading!