Tag Archives: key-value

Hash Table with Embedded Hash Table and Array

Sometimes I write something—as in some PowerShell—and I feel like, while I don’t need it right now and here today, I should put it somewhere. I just found a screenshot where I did that. Maybe it’ll help someone, and posting it here on my site will likely allow me to find it when I’ll need it, versus looking around on random computers for random screenshots. I would’ve never found this image were I actually looking for it.

I must’ve wondered, can I embed both a hash table and an array in a hashtable? I can. First, however, let’s start with a single, simple array, and a single simple hashtable. Let’s make sure we know these.

An array is a collection—remember that word, as you’ll hear it again in PowerShell (in place of “array”)—of items. In other languages, you might hear it referred to as a list. That’s not a bad visual. I write what I need at the grocery store on a Post-it note. I suppose it’s an array; it is a collection of items that I need at home, whether it be food, cleaning supplies, or something else. In the next example, we’ll create two identical arrays in two different manners—one without and one with the array sub-expression operator—and store them in two separate variables.

$ArrayWithoutOperator = 'e','f','g'
$ArrayWithOperator = @('e','f','g')
$ArrayWithoutOperator
e
f
g
$ArrayWithOperator
e
f
g

Let’s prove that at least one of these is an array. While I practically never use Format-Table, I’ve used it in this example to ensure all the output is packed as closely as possible to the left.

ArrayWithoutOperator.GetType() | Format-Table -AutoSize
IsPublic IsSerial Name     BaseType
-------- -------- ----     --------
True     True     Object[] System.Array

It is!

A hash table—and this is my favorite way in which to explain it—is an associative array. Huh? It’s still an array or a list, but now, each item has an association. Each item in the array contains a key and a value. Take a look, keeping in mind that PowerShell will label the keys with “Name” (while the value will be labeled with “Value”).

$Hashtable = @{'mid1' = 'c';'mid2' = 'd'}
$Hashtable
Name                           Value
----                           -----
mid2                           d
mid1                           c

Now, let’s recreate our array and our hash table inside of another hash table. I’m going to show this using both a single line and multiple lines. It’s important to see those semicolons.

@{'top1' = 'a';'top2' = 'b';'top3' = @{'mid1' = 'c';'mid2' = 'd'}; 'bottom1' = @('e','f','g')}

@{
    'top1'    = 'a'
    'top2'    = 'b'
    'top3'    = @{'mid1' = 'c';'mid2' = 'd'}
    'bottom1' = @('e','f','g')
}
Name                           Value
----                           -----
top2                           b
bottom1                        {e, f, g}
top3                           {[mid2, d], [mid1, c]}
top1                           a

That output is painful. As you may have been able to guess, based on the values, I wanted to see elements labeled using “top” at the top of this list, and the element using “bottom” at the bottom. This is how hash tables work in PowerShell in my experience: You’re not going to get it back the way you might expect. Therefore, you’re going to need to know about the ordered attribute which you can apply to a hash table to create an ordered dictionary.

[ordered]@{
    'top1'    = 'a'
    'top2'    = 'b'
    'top3'    = @{'mid1' = 'c';'mid2' = 'd'}
    'bottom1' = @('e','f','g')
}
Name                           Value
----                           -----
top1                           a
top2                           b
top3                           {[mid2, d], [mid1, c]}
bottom1                        {e, f, g}

Now that we have it in the order in which we expect, let’s pay a bit more attention to the associated values for each key. The key top3 is our embedded, or nested, hash table. We can see the representation in the value, where the nested keys and associated value are displayed as [mid2, d], [mid1, c] indicating a hash table (or associative array). Our value for the bottom1 key is e, f, g, indicating an array. And as easy as that, a hash table can be a container for additional hash tables and arrays.

Read-Host Prompt inside Hash Table

I’m working with Plaster and in doing so, have a few hash tables in my workspace. Suddenly, and out of nowhere, I had a thought: Can I put a Read-Host command, as the value of a key-value pair inside of a hash table? Yes, but before we get too far into this, here’s a simple hash table example without any Read-Host commands.

$Params = @{
    meal = 'lunch'
    food = 'Ramen'
    drink = 'Tea'
}
$Params

Name                           Value
----                           -----
drink                          Tea
food                           Ramen
meal                           lunch

Okay, that was simple: Choose a variable name, prefix it with a dollar sign, create the hash table structure as @{}, and then add key-value pairs as <key> = <value>.

Now, on to a Read-Host example. Read-Host is a cmdlet that can be used to interactively prompt a user for a value. It’s not always preferred, or the right to do, but there are times when it can be useful, and where its use is acceptable. In the next example, we’ll create a single key-value pair ourselves, then we’ll prompt the user for a value to assign to the Number key. As you will also determine, when prompted, the word “five” is entered, and sure enough, the entry ends up as the value for the Number key in our hash table.

Remove-Variable -Name Params
$Params = @{
    Color = 'red'
    Number = Read-Host -Prompt 'Enter spelled out number'
}
$Params
Enter spelled out number: five

Name                           Value
----                           -----
Number                         five
Color                          red

This example was one of those “can I do this moments?” Sure, I was able to return the $Params hash table with the correct value in the Number key after having been prompted for that value. This occurred, as the hash table was being defined and built. I didn’t even know if that would work, but now we both know that it does.

In the next example, we try something even more obscure, but as suspected, it doesn’t work. We first assign the Random key the value of a Read-Host prompt. As we’ve seen, that does work. Next, while still creating keys and values, we take the value assigned to the Random key in the $Params hash table and attempt to assign it to the Number key, as well. Again, this doesn’t work. As suspected, we can’t use the $Params hash table until it’s done being created. It’s not a shock, but it was worth a try, of course.

Remove-Variable -Name Params
$Params = @{
    DayOfWeek = 'Friday'
    Random = Read-Host -Prompt 'Enter spelled out number'
    Number = $Params.Random
}
$Params
Enter spelled out number: three

Name                           Value                                                                                                                             
----                           -----                                                                                                                             
Random                         three
Number
DayOfWeek                      Friday

Even if this did work, I’m not sure how this would ever really serve a purpose, but it’s always worth trying something even if doesn’t seem plausible. And if it did work, I don’t expect that we’d even need duplicate values in different keys anyway, and that’s all we’d be doing. But all that said, we absolutely can use Read-Host to assign a value to a key in a hash table, as it’s being created.

Alright, that was it. Enjoy the week!