Adding and Removing Items from a PowerShell Array

Adding and removing Items from a PowerShell array is a topic which can lead to some confusion, so here are a few tips for you.

Create an array and we will note the type System.Array:


$Fruits = "Apple","Pear","Banana","Orange"

$Fruits.GetType()

Array01

However, if we try to Add or Remove items to the array we get errors that the “Collection was of a fixed size”


$Fruits.Add("Kiwi")
$Fruits.Remove("Apple")
$Fruits.IsFixedSize

Array02

We can see that the array we originally created is of a fixed size. The MSDN page for the ISFixedSize Property helps to explain this. Note it supports the modification of existing elements, but not the addition or removal of others.

Array03

One way to deal with this is to use a System.Collections.ArrayList instead


[System.Collections.ArrayList]$ArrayList = $Fruits
$ArrayList.GetType()

Array04

Now if we try the previous add and remove methods we are successful:


$ArrayList.Add("Kiwi")
$ArrayList
$ArrayList.Remove("Apple")
$ArrayList

Array05

Alternatively, if we had stuck with the original Array object we could do the following to ‘add’ an item to it. (Actually it creates a new array with an additional item)


$New = $Fruits += "Kiwi"
$New
$New.GetType()

Array06

However, we can’t remove items in this way:


$New2 = $Fruits -= "Apple"

Array07

We could instead do this:


$New3 = $Fruits -ne "Apple"
$New3

Array08

 

Update: Thanks to Rob Campbell for pointing out another way to do this.

Taking your initial array you can convert it to a System.Collections.ObjectModel.Collection`1 like this, which may be easier to remember than using the full type name of either a collection or array list:


$Collection = {$Fruits}.Invoke()
$Collection
$Collection.GetType()

Array09

Now we can add and remove items using the Add and Remove methods:


$Collection.Add("Melon")
$Collection
$Collection.Remove("Apple")
$Collection

Array10

13 thoughts on “Adding and Removing Items from a PowerShell Array

  1. Good Write up, thank you!
    I personally use this construct to create an empty arraylist:

    $ArrList = [System.Collections.ArrayList]@()

    to bad that the PowerShell Team did not decided to use the Arraylist as defalt type. I think it has its reson.

    greets Peter Kriegel
    German PowerShell community
    http://www.PowerShell-Group.eu

  2. But when I am using with -expandproperty, multivalue attributes .Remove doesn’t work. Here From is having multiple values & I want to get rid of One. But could not. Remove doesn’t throw any error but doesn’t remove the item. I am still using that -ne method though.

    $SenderEmailIDs = Get-TransportRule “General – Bypass Spam Filtering – Sender EmailID Based” | select -ExpandProperty From
    [System.Collections.ArrayList]$ArrayListS = $SenderEmailIDs
    $SenderEmailIDs.count = 183
    $ArrayListS.count = 183
    $ArrayListS.Remove(“”)
    $ArrayListS.count = 183

  3. Try
    $ArrayListS.Remove($ArrayListS[2])
    2 – index number of element

    it works with aduser fine

    to find index

    $p = $ar[2]
    [array]::IndexOf($ar,$p)

  4. Can you help me wrap my head around whats happening here?

    [array]$arrADComputers = Get-ADComputer -Filter 'OperatingSystem -like "Windows 7 Enterprise" ' -Properties Name | select name
    $arrADComputers.GetType()
    $arrADComputers.count
    # this fails of course - expected
    $arrADComputers.Remove("Machine")
    $arrADComputers.count

    # lets try with System.Collections.ObjectModel.Collection`1
    $Collection1 = {$arrADComputers}.Invoke()
    $Collection1.GetType()
    $Collection1.Count
    $Collection1.Remove("Machine")
    $Collection1.count

    # lets try with System.Collections.ArrayList
    [System.Collections.ArrayList]$Collection2 = $arrADComputers
    $Collection2.GetType()
    $Collection2.Count
    $Collection2.Remove("Machine")
    $Collection2.count

    What concept am I not grasping that’s preventing items from getting removed from the array?

  5. Julius or anybody else if they are having the same issue

    $Collection1 = {$arrADComputers.name}.Invoke()

  6. I got a weird, issue. Trying to Create a Custom PSobject with a foreach loop for the Properties. Looks like that’s not possible

    In the Example below:
    1) I make an Empty Array $object1
    2) Items is an Array containing Data1,Data2 <–basically a csv, 1 string split with a comma
    3) I create a new psobject and splat the properties, the key is the first item from the split and the value is the second item from the split.
    4) After creating the new object, I tell Powershell to add it back into the Empty array.

    # $object1=@()
    # foreach ($item in $items){
    # $Object2=New-Object psobject -Property @{
    # $data.split(",")[0] = $data.split(",")[1]
    # }
    # $object1 += $Object2
    # }

    Now for the weird part, if you | GM the object, You only get 1 property value, not everything.

    $object1 | GM

    TypeName: System.Management.Automation.PSCustomObject

    Name MemberType Definition
    —- ———- ———-
    Equals Method bool Equals(System.Object obj)
    GetHashCode Method int GetHashCode()
    GetType Method type GetType()
    ToString Method string ToString()
    ARCHIVE NoteProperty System.String ARCHIVE=305.86

    NOTE: only 1 property gets set, Archive. Here goes the same operation with out the foreach logic

    $object=
    New-Object psobject -Property @{
    ARCHIVE = $datas[0].split(",")[1]
    BACKUP = $datas[1].split(",")[1]
    FULL_DBBACKUP = $datas[2].split(",")[1]
    MIGRATION =$datas[3].split(",")[1]
    RECLAMATION =$datas[4].split(",")[1]
    RETRIEVE =$datas[5].split(",")[1]
    }

    $object | GM

    TypeName: System.Management.Automation.PSCustomObject

    Name MemberType Definition
    —- ———- ———-
    Equals Method bool Equals(System.Object obj)
    GetHashCode Method int GetHashCode()
    GetType Method type GetType()
    ToString Method string ToString()
    ARCHIVE NoteProperty System.String ARCHIVE=305.86
    BACKUP NoteProperty System.String BACKUP=3941.60
    FULL_DBBACKUP NoteProperty System.String FULL_DBBACKUP=75.23
    MIGRATION NoteProperty System.String MIGRATION=1903.58
    RECLAMATION NoteProperty System.String RECLAMATION=443.16
    RETRIEVE NoteProperty System.String RETRIEVE=14.75

    In theory the foreach logic should work. whats really odd, the foreach logic DOES contain the properties, they're just not visible, $object1.backup will return a value but as you can see in the | GM, its just not visible. Can anyone explain?

  7. Removing item (e.g. $o) from array ($arr) is possible like this: $arr = $arr | Where { $_ -ne $o }. Of course it has a performance hit as it creates a new array instead of removing from the existing one, however for small scripts working on fix size arrays anyway is often tolerable.

  8. I realize the post is nearly three years old, but here’s another simple way (to add at least):

    $fixedArray = @(“hello”, “goodbye”)
    $fixedArray = @($fixedArray, “greetings”)

    Chris

Leave a Reply

Your email address will not be published. Required fields are marked *