How to initialize an array of custom objects
Here is a concise way to initialize an array of hashtables in PowerShell.
> $body = @( @{ Prop1="1"; Prop2="2"; Prop3="3" }, @{ Prop1="1"; Prop2="2"; Prop3="3" } )
> $body
Name Value
---- -----
Prop2 2
Prop1 1
Prop3 3
Prop2 2
Prop1 1
Prop3 3
Maybe you mean like this? I like to make an object and use Format-Table:
> $array = @()
> $object = New-Object -TypeName PSObject
> $object | Add-Member -Name 'Name' -MemberType Noteproperty -Value 'Joe'
> $object | Add-Member -Name 'Age' -MemberType Noteproperty -Value 32
> $object | Add-Member -Name 'Info' -MemberType Noteproperty -Value 'something about him'
> $array += $object
> $array | Format-Table
Name Age Info
---- --- ----
Joe 32 something about him
This will put all objects you have in the array in columns according to their properties.
Tip: Using -auto
sizes the table better
> $array | Format-Table -Auto
Name Age Info
---- --- ----
Joe 32 something about him
You can also specify which properties you want in the table. Just separate each property name with a comma:
> $array | Format-Table Name, Age -Auto
Name Age
---- ---
Joe 32
I'd do something along these lines:
$myitems =
@([pscustomobject]@{name="Joe";age=32;info="something about him"},
[pscustomobject]@{name="Sue";age=29;info="something about her"},
[pscustomobject]@{name="Cat";age=12;info="something else"})
Note that this only works in PowerShell 3, but since you did not mention the version in your question I'm assuming this does not matter for you.
Update
It has been mentioned in comments that if you do the following:
$younger = $myitems | Where-Object { $_.age -lt 20 }
Write-Host "people younger than 20: $($younger.Length)"
You won't get 1
as you might expect. This happens when a single pscustomobject
is returned. Now this is not a problem for most of other objects in PowerShell, because they have surrogate properties for Length
and Count
. Unfortunately pscustomobject
does not. This is fixed in PowerShell 6.1.0. You can work around this by using operator @()
:
$younger = @($myitems | Where-Object { $_.age -lt 20 })
For more background see here and here.
Update 2
In PowerShell 5 one can use Classes to acheive similar functionality. For example you can define a class like this:
class Person {
[string]$name
[int]$age
[string]$info; `
`
Person(
[string]$name,
[int]$age,
[string]$info
){
$this.name = $name
$this.age = $age
$this.info = $info
}
}
Backticks here are so that you could copy and paste it to the command line, they are not required in a script. Once the class is defined you can the create an array the usual way:
$myitems =@([Person]::new("Joe",32,"something about him"),
[Person]::new("Sue",29,"something about her"),
[Person]::new("Cat",12,"something else"))
Note that this way does not have the drawback mentioned in the previous update, even in PowerShell 5.
Update 3
You can also intialize a class object with a hashtable, similar to the first example. For that you need to make sure that a default contructor defined. If you do not provide any constructors, one will be created for you, but if you provide a non-default one, default constructor won't be there and you will need to define it explicitly. Here is an example with default constructor that is auto-created:
class Person {
[string]$name
[int]$age
[string]$info;
}
With that you can:
$person = @([Person]@{name='Kevin';age=36;info="something about him"}
[Person]@{name='Sue';age=29;info="something about her"}
[Person]@{name='Cat';age=12;info="something else"})
This is a bit more verbose, but also a bit more explicit. Thanks to @js2010 for pointing this out.