Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do some arrays mirror each other in PowerShell?

Tags:

powershell

I am using PowerShell 2.0. When I make a new variable as an array and then set another variable to be equal to the first one, the second variable "mirrors" the first one. After changing an object in the original array, the exact same change appears in the second array. For instance,

$array0001 = 6, 7, 3, 4, 0
$array0002 = $array0001
$array0001[3] = 55
$array0002

with the output being

6
7
3
55
0

I notice that when you set the second variable to have the same value as the first variable, except this time enclosed within a subexpression operator, modifications to the first array do not affect the second array. For instance,

$array0001 = 6, 7, 3, 4, 0
$array0002 = $($array0001)
$array0001[3] = 55
$array0002

with the output being

6
7
3
4
0

Why does enclosing the value in a subexpression operator change the behavior of the variable? Is there another or better way to avoid making array variables that "mirror" each other?

ETA: I have now found that $array0002 = @($array0001) and $array0002 = &{$array0001} both accomplish the exact same objective.

like image 290
sine62677 Avatar asked Jun 08 '17 18:06

sine62677


People also ask

What does @() mean in PowerShell?

Array subexpression operator @( )Returns the result of one or more statements as an array. The result is always an array of 0 or more objects. PowerShell Copy.

How do arrays work in PowerShell?

To create and initialize an array, assign multiple values to a variable. The values stored in the array are delimited with a comma and separated from the variable name by the assignment operator ( = ). The comma can also be used to initialize a single item array by placing the comma before the single item.

How do I compare two arrays in PowerShell?

You can also use PowerShell to compare arrays using the Compare-Object cmdlet. This cmdlet takes a reference object and a difference object and returns a side indicator indicating which elements are and are not in either array. You can see below that the Compare-Object cmdlet allows you to compare both arrays at once.

What is $_ in PowerShell?

The “$_” is said to be the pipeline variable in PowerShell. The “$_” variable is an alias to PowerShell's automatic variable named “$PSItem“. It has multiple use cases such as filtering an item or referring to any specific object.


2 Answers

It's called "pass by reference". Instead of actually assigning a value, you're assigning a reference to another location that holds a value. If the value in the original location changes, the reference you made is pointing to that original location, and will see the updated value.

Most languages have ways to "pass by reference" and "pass by value". That's what you found by doing $array0002=$($array0001). Neither one is better than the other, they just both have different uses.

In PowerShell you can also put .value behind your reference to grab the value, instead of the reference.

like image 177
coinbird Avatar answered Sep 30 '22 22:09

coinbird


When setting one array equal to another like that, the different variables are simply referencing eachother, it's not a true copy. This is essentially the same thing that you are asking. From that link, serializing the data to do a deep copy is a good way around it.

#Original data
$Array1 

# Serialize and Deserialize data using BinaryFormatter
$ms = New-Object System.IO.MemoryStream
$bf = New-Object System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
$bf.Serialize($ms, $Array1)
$ms.Position = 0

#Deep copied data
$Array2 = $bf.Deserialize($ms)
$ms.Close()
like image 34
Nick Avatar answered Sep 30 '22 22:09

Nick