Variables, arrays and hashtables
Store values in typed variables, lists in arrays, and lookups in hashtables - and splat parameters.
- Create variables, convert between types and use type constraints
- Build, index, slice and grow arrays
- Use hashtables for lookups and splatting
Variables start with $ and spring into existence when you assign them: $keeper = 'Ada'. Names are case-insensitive, and a variable can hold any type of object. To pin down a type, put it in brackets:
- Casting converts a value once:
[int]'42',[datetime]'2026-12-25',[string]3.5. - Type constraints keep converting every later assignment too: after
[int]$meals = 3, assigning'4'stores the number 4, and assigning'lots'is an error.
Common type names: [int], [double], [decimal], [string], [bool], [datetime], [timespan], [array], [hashtable]. They’re short names (“type accelerators”) for .NET types.
1$wingspan = '12'
2$wingspan + 3
3[int]$wingspan + 3
43 + $wingspan
5[int]$meals = 3
6$meals = '4'
7$meals.GetType().Name
8$hatched = [datetime]'2026-12-25'
9($hatched - [datetime]'2026-10-02').Days
10[math]::Round(7 / 2)
11[math]::Max(12, 15)123 15 15 Int32 84 4 15
The first two lines show the left-side rule again: '12' + 3 joins text to make 123, while 3 + '12' adds numbers. Subtracting two dates gives a TimeSpan with .Days, .Hours and friends. And [math]::Round(7 / 2) is 4 - but watch out, .NET rounds halves to the nearest even number by default, so [math]::Round(2.5) is 2.
Arrays
| Syntax | Means |
|---|---|
$crew = 'Ada', 'Grace', 'Linus' | a comma makes an array |
@() / @('Ada') | an empty array / always an array, even with one item |
1..5 | a range: 1, 2, 3, 4, 5 |
$crew[0], $crew[-1] | first, last |
$crew[0..1] | a slice |
$crew.Count | how many |
$crew += 'Ken' | append (builds a new, longer array) |
$crew -contains 'Ada' | is it there? |
+= copies the whole array every time, which gets slow for thousands of items. For big collections use a list: $list = [System.Collections.Generic.List[string]]::new() then $list.Add('Ada') - or just let a loop’s output collect into a variable: $squares = foreach ($n in 1..1000) { $n * $n }.
1$dragons = 'Ember', 'Glim', 'Skyla'
2$dragons += 'Pebble'
3"$($dragons.Count) dragons, first $($dragons[0]), last $($dragons[-1])"
4$dragons[1..2] -join ' & '
5$dragons | Sort-Object | Select-Object -First 1
6$squares = foreach ($n in 1..4) { $n * $n }
7$squares -join ','
8$one = @('Vesper')
9$one.Count4 dragons, first Ember, last Pebble Glim & Skyla Ember 1,4,9,16 1
Hashtables
A hashtable maps keys to values: $diet = @{ Firedrake = 'goats'; Wyrm = 'mushrooms' }. Read with $diet.Wyrm or $diet['Wyrm'], add or change with $diet.Wisp = 'moths', check with $diet.ContainsKey('Wisp'), and remove with $diet.Remove('Wyrm'). Keys ignore case.
Hashtables don’t keep their order; [ordered]@{ ... } does (it’s a slightly different type: check its keys with .Contains() rather than .ContainsKey()). To loop over the pairs, use $diet.GetEnumerator() (each item has .Key and .Value) - or $diet.Keys.
1$diet = [ordered]@{ Firedrake = 'goats'; Wyrm = 'mushrooms' }
2$diet.Wisp = 'lantern moths'
3$diet['firedrake']
4$diet.Contains('Stormwing')
5foreach ($entry in $diet.GetEnumerator()) {
6 '{0,-10} eats {1}' -f $entry.Key, $entry.Value
7}
8$diet.Countgoats False Firedrake eats goats Wyrm eats mushrooms Wisp eats lantern moths 3
One more hashtable superpower: splatting. Put parameter names and values in a hashtable and pass it with @ instead of $. Long commands become readable, and you can build the parameters up conditionally:
1$dateParameters = @{
2 Year = 2027
3 Month = 2
4 Day = 14
5 Format = 'dddd d MMMM'
6}
7Get-Date @dateParametersSunday 14 February
Key takeaways
Variables are created on assignment;
[type]casts once, and[type]$varconstrains for good.Arrays:
,or@(), index from 0 (or -1 for the last), slice with ranges; prefer loop output or lists over+=in big loops.Hashtables map keys to values;
[ordered]keeps their order.Splatting (
Command @params) passes a hashtable as parameters.
Lesson quiz
7 questions · pass with 5 correct · up to 50 XP
Passing this quiz completes the lesson and keeps your streak going. Questions you miss come back in review sessions later.
Practice: write PowerShell scripts
Write a script in the editor and run it for real against sample input, which is piped into your script as $input. Scripts run on PowerShell 6.2 through Try It Online (tio.run), a free public service, so these exercises avoid PowerShell 7-only syntax; your script and test input are sent there.
Keeper roster
Each input line is a keeper’s name. Collect them into an array, then print:
14 keepers
2first on shift: Ada
3last on shift: Linus
4alphabetical: Ada, Grace, Ken, Linus- Four keepers
- Two keepers
Lessons teach PowerShell 7; your script runs on PowerShell 6.2 via Try It Online (tio.run), a free public service, so stick to syntax that works there. Test input is piped into your script as $input. Your script and test input are sent to that service.
Diet lookup
The starter has a hashtable of what each species eats. Each input line is Name Species. Print Ember the Firedrake eats goats, or Glim the Wisp eats ??? - ask a keeper for species not in the table. Finally print unknown species: N.
- Mixed
- All known
Lessons teach PowerShell 7; your script runs on PowerShell 6.2 via Try It Online (tio.run), a free public service, so stick to syntax that works there. Test input is piped into your script as $input. Your script and test input are sent to that service.
Questions about this lesson
Stuck? Ask. Figured something out? Share it. Explaining is one of the best ways to learn.
Loading posts…