Adding Array Index Numbers to PowerShell Custom Objects

Adding Array Index Numbers to PowerShell Custom Objects

  • Comments 2
  • Likes

Summary: Microsoft Scripting Guy, Ed Wilson, talks about adding array index numbers to Windows PowerShell custom objects.

Hey, Scripting Guy! Question Hey, Scripting Guy! Our software application returns arrays of information. What I need is a way to artificially add the array element number to the object that the cmdlet outputs. For example, I want to add the highlighted information to the following output, and I need the highlighted numbers to be the array indexes:

Image of command output

Can you help me?

—WS

Hey, Scripting Guy! Answer Hello WS,

Microsoft Scripting Guy, Ed Wilson, is here. Well it is just a couple of days until the Scripting Wife’s birthday. Shhhhhh…don’t tell her that I have not forgotten. It is sort of a game we like to play. I pretend to forget it is her birthday, she pretends to be upset. In the end, I wind up getting her great presents that she really likes—such as the complete series of the old Get Smart television show. She is still talking about that present!

So WS, when I first read your email sent to scripter@microsoft.com, I thought, “Well, that will not be too hard. Maybe I will use Select-Object, add a custom column, and pick up the index number.”

Well unfortunately, that did not work out too well.

I do not have your custom software package installed, but that really does not matter because PowerShell is PowerShell is PowerShell. It always behaves the same.

What I ended up doing was creating a custom PSObject and using the IndexOf method to pick up the index number. Then I added in the value of the array element. Here is an example of what I am talking about:

PS C:\> $array = "dog","cat","mongoose","bird"

PS C:\> $array.IndexOf('dog')

0

PS C:\> $array.IndexOf('mongoose')

2

PS C:\>

As you can see in the previous script, the IndexOf method will accept an array value and return the associated index number from it. So here is how I added this into a little demo script:

# -----------------------------------------------------------------------------

# Script: ArrayIndexAndValues.ps1

# Author: ed wilson, msft

# Date: 09/06/2013 11:33:26

# Keywords: Scripting Techniques, Arrays, Custom PSObjects

# comments:

# HSG-9-23-2013

# -----------------------------------------------------------------------------

$array = "dog","cat","mongoose","bird"

Foreach($a in $array)

{

New-Object -TypeName psobject -Property @{

    index= $array.indexof($A)

    Value= $A } }

But I was not really happy with my answer. So I emailed Lee Holmes and asked his opinion. Here is his answer…

First of all, there is no really nice way to do what you are attempting to do. There’s an example from my Windows PowerShell Cookbook, second version, which talks about how to add Add-FormatTableIndexParameter to Format-Table. But other than that, an approach similar to yours is good.

Using Array.IndexOf() will be a little slow. Here is an alternative:

dir c:\ | Foreach-Object { $index = 0 } {

    [PSCustomObject] @{ Index = $index; Object = $_ }; $index++

}

WS, that is all there is to using Windows PowerShell to add array index values to a custom object. Join me tomorrow when we will have a great guest blog post by Microsoft PowerShell MVP, Jeffrey Hicks. He’ll be talking about a script profile tool that he wrote. It is good stuff and you do not want to miss out.

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,

    I hope that you and Teresa are fine ...  :-)

    Well, the solution presented here is definitely fine, too!

    I have often done the same in a slightly different way like:

    $array.GetLowerBound(0)..$array.GetUpperBound(0) | %{ [PsCustomObject] @{'Index'=$_; 'value'=$array[$_]} }

    or if you can be sure that the lower bound is 0:

    0..($array.Count) | %{ [PsCustomObject] @{'Index'=$_; 'value'=$array[$_]} }

    In fact it is not too different ...

    Greetings,

    Klaus

  • Variations that canbeuseful:

    $sl=New-Object system.collections.sortedlist

    $i=0;Get-Process|%{[system.collections.sortedlist]$sl.Add($i++,$_)}

    And

    $al=New-Object System.Collections.ArrayList

    $p=Get-Process

    $al.AddRange($p)

    Can you guess what is useful about an ArrayList object?