Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to initialize an array of custom objects

First, as this leads to my question, I'll start by noting that I've worked with XML a fair bit in PowerShell, and like how I can read data from XML files, quickly, into arrays of custom objects. For example, if I had the following XML file:

<stuff>  <item name="Joe" age="32">   <info>something about him</info>  </item>  <item name="Sue" age="29">   <info>something about her</info>  </item>  <item name="Cat" age="12">   <info>something else</info>  </item> </stuff> 

And if I read it in simply, like this:

[xml]$myxml = Get-Content .\my.xml 

Then I can get to an array of my items like this:

[array]$myitems = $myxml.stuff.Item $myitems  name   age  info ----   ---  ---- Joe    32   something about him Sue    29   something about her Cat    12   something else 

So, now my question:

How can I create a similar structure of an array of custom objects, and initialize them in my script, without reading a file?

I can do lots of looping and/or lots of creating/initializing individual objects, and then add to an array one at a time...

But it seems there should be a way to perform this creation/initialization in a simpler way. Note that the key here, is that my custom objects have more than two elements (otherwise, I'd have used a hash).

I've even looked at creating a big string of XML, and using Select-XML, but I just couldn't get the syntax right (if that was even the right road to be heading down).

like image 416
SteveDJ Avatar asked Jun 27 '13 21:06

SteveDJ


People also ask

How do you initialize a custom array in Java?

We can declare and initialize arrays in Java by using a new operator with an array initializer. Here's the syntax: Type[] arr = new Type[] { comma separated values }; For example, the following code creates a primitive integer array of size 5 using a new operator and array initializer.

How do you initialize an object in an array?

One way to initialize the array of objects is by using the constructors. When you create actual objects, you can assign initial values to each of the objects by passing values to the constructor. You can also have a separate member method in a class that will assign data to the objects.

How do you create a custom array?

In this article we will see that how we can create arrays of custom types. We can achieve it by using custom types. We all know that array is a reference type i.e. memory for an array is allocated in a heap. Sometimes we need to declare arrays of custom types rather than arrays of predefined types ( int or string etc).

How do you declare and initialize an array of objects in Java?

We declare an array in Java as we do other variables, by providing a type and name: int[] myArray; To initialize or instantiate an array as we declare it, meaning we assign values as when we create the array, we can use the following shorthand syntax: int[] myArray = {13, 14, 15};


2 Answers

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.

like image 85
Andrew Savinykh Avatar answered Sep 17 '22 21:09

Andrew Savinykh


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   
like image 29
Shaun Luttin Avatar answered Sep 18 '22 21:09

Shaun Luttin