Easily Create and Manipulate an Array of Arrays in PowerShell

Easily Create and Manipulate an Array of Arrays in PowerShell

  • Comments 4
  • Likes

Summary: Learn about creating an array of arrays in Windows PowerShell, and see how to store numerical data and rich objects in elements.

Microsoft Scripting Guy, Ed Wilson, is here. Yesterday in Charlotte, North Carolina in the United States, it was 60 degrees Fahrenheit (that is 15 degrees Celsius according to my unit conversion module). I was bragging about this to my friend, George, who lives in Ottawa, Canada. Today it is 32 degrees Fahrenheit (0 degrees Celsius—I don’t need a unit conversion module to do that one), and there is frost on the ground. I guess that is what I get for bragging.

Anyway, the Scripting Wife and I are back in Charlotte, after our quick trip to Phoenix, Arizona to speak at the Arizona PowerShell Users Group meeting. The event was great, and they are the perfect hosts. In fact, we are planning an International PowerShell Users Group Day in conjunction with them, which should happen in the spring of 2012. Stay tuned for more information on this exciting event.

Note: This is the fifth post in a series of blog posts that are devoted to discussing working with arrays in Windows PowerShell.

Creating an array of arrays

One of the cool things to do with an array is to create an array that contains other arrays. In Windows PowerShell this is super easy. It is as easy to create an array of arrays as it is to create a single dimensional array. Here are the steps to create an array of arrays:

  1. Create an array and store it in a variable.
  2. Create additional arrays, and store them in variables as well.
  3. Use the previously created arrays and separate them with the comma operator.
  4. Assign the arrays to a variable.

The following code creates four arrays and stores the arrays in variables. It then assigns each of the newly created arrays to a different element in a new array named $array.

PS C:\> $a = 1..5

PS C:\> $b = 6..10

PS C:\> $c = 11..15

PS C:\> $d = 16..20

PS C:\> $array = $a,$b,$c,$d

Accessing elements in an array of arrays

To access items from an array of arrays, use the square-bracketed “array” notation. For example, to see the first array of items, which are stored in element 0, use [0]. This code is shown here.

$array[0]

What is cool is that element 0 contains an array, so an array returns in response to the command. In the following command, I return the array previously stored in element 0. To save space in the output, I join the elements of the array with a space between each element. Here is the command to display the array that is stored in element 0 and to return the elements on a single line.

PS C:\> $array[0] -join " "

1 2 3 4 5

Each of the other arrays that I stored in the other elements of $array are accessed in the same manner. The following code displays the information that is contained in the remaining elements of the $array array.

PS C:\> $array[1] -join " "

6 7 8 9 10

PS C:\> $array[2] -join " "

11 12 13 14 15

PS C:\> $array[3] -join " "

16 17 18 19 20

If I want to access a specific element from one of the arrays that is stored in one of the elements of the $array array, I again use the square bracket (array) notation. This time, I also specify the specific element from the array that is contained in the element. Therefore, to access element 1 in the $b array (stored in element 1 of $array), I use the notation that is shown here.

$array[1][1]

To access the third element of the array, which is stored in the third element of $array, the syntax is as shown here.

$array[3][3]

The following image shows the code and the output from creating four arrays and storing them in variables a-d, creating an array that holds the four arrays, displaying the values from each element, and then accessing element 1,1 and element 3,3.

Image of command output

One of the fun things to do, instead of just storing numbers in arrays, is to use the array for temporary storage. For example, in the following code, I store the results of three different WMI queries into three different variables. I then create three different arrays with cherry-picked properties from each of the stored WMI results. Next, I create an array of arrays by building a new array.

$comp = gwmi win32_computersystem

$os = gwmi win32_operatingsystem

$bios = gwmi win32_bios

$a = $comp.UserName, $comp.DNSHostName, $comp.Domain

$b = $os.caption, $os.buildnumber, $os.OSArchitecture

$c = $bios.name, $bios.description, $bios.manufacturer

$array = $a,$b,$c

When I have my array of arrays, I can index into any of the values that I need to access. A few of the elements are shown here.

PS C:\> $array[0]

IAMMRED\ed

newMrEd

iammred.net

PS C:\> $array[0][1]

newMrEd

PS C:\> $array[1]

Microsoft Windows 7 Ultimate

7601

64-bit

PS C:\> $array[1][0]

Microsoft Windows 7 Ultimate

PS C:\> $array[2][1]

BIOS Date: 05/04/11 17:11:33 Ver: 04.06.04

The commands to store three different WMI queries in three different variables, build up an array of arrays, and access different elements of the arrays are shown in the following image.

Image of command output

One thing that has intriguing possibilities is to store rich objects in an array. In the following example, I store the results of Get-Service, Get-Process, and Get-Date in their own variables. Next, I create an array of these objects.

$a = Get-Service

$b = Get-Process

$c = get-date

$array = $a,$b,$c

When I have the array of objects stored, I can index into them just like anything else.

PS C:\> $array[2]

Thursday, December 01, 2011 5:31:12 PM

Because there is only one DateTime object, if I attempt to go any deeper with this object, an error arises. The command and the associated error are shown here.

PS C:\> $array[2][1]

Unable to index into an object of type System.DateTime.

At line:1 char:11

+ $array[2][ <<<< 1]

    + CategoryInfo          : InvalidOperation: (1:Int32) [], RuntimeException

    + FullyQualifiedErrorId : CannotIndex

But with the processes and services in the array elements, we have a collection of arrays. I can access them directly. I illustrate this here.

PS C:\> $array[1][0]

 

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName

-------  ------    -----      ----- -----   ------     -- -----------

    671      41    31700      38604   187   100.79   7284 AnalogRec13

 

In fact, I can even use dotted notation to access individual property values from individual processes. This technique is shown here.

PS C:\> $array[1][0].id

7284

Well, that is all there is to using and working with arrays. Tomorrow, I will talk about hash tables. Hope to see you then.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • Hi Ed,

    this is a great blog entry demonstrating the power of arrays!

    Being able to put any object into an array is fanastic!

    Building an array of arrays is sometimes really a good idea!

    There are two topics to keep in mind, if you choose complex datastructures like jagged arrays of objects!:

    1.. Don't make things unnecessarily complicated if you stack two many array dimensions into each other!

    Have a look of how you can access array elements. If it is too confusing consider alternative data structures to keep scripts clear

    2. Consider creating typed arrays if you know that you definitely expect data of the same kind!

    Typed arrays like

    [sting[]] $myStringArray="one","two","three"

    [int[]] MyIntArray=1,2,3

    or even

    [System.Diagnostics.Process[]]$ps=ps

    may save memory,, reduce access time and even help to avoid errors!

    Klaus

  • @Klaus Schulte thank you so much for your comments. You are absolutely correct about keeping things simple, as well as creating strongly typed arrays. I nearly always prefer simple code to complex code. With simple code, it is easier to read and to understnad what the code does. This makes it easier to avoid errors from the outset. It also makes it easeir to correct problems if they arise.

  • If a string variable contains "printer1 printer2", how do I stuff this into a array? I tired:
    $plist = @($myvariable)
    and tested it with:
    $plist -is [system.array]
    which returns true.
    However:
    foreach ($printer in $plist)
    {$printer}

    returns just one line
    printer1 printer2

    I initialized $myvariable = "printer1", "printer2" so I'm really confused.

    Art

  • @Art

    $myvariable = "printer1", "printer2
    $myVariable.GetType()

    ?? what do you think you will get?