![]() |
![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ![]() |
| Welcome to Windows Vista Forums. Our forum is dedicated to helping you find solutions with any problems, errors or issues you are experiencing with Windows Vista. The Vista forum also covers news and updates and has an extensive Windows Vista tutorial section that covers a wide range of tips and tricks. |
| |||||||
![]() |
| |
| | #1 (permalink) |
| | Copying an array and weird things about updating arrays... Hi, I'm new to powershell and in my messing around I've found that array assignments behave pretty interestingly. It would be great if someone could explain 1/ the right way to do this and 2/ exactly why I'm seeing what I do... PS C:\Documents and Settings\Bruce> $c=1,2,3 PS C:\Documents and Settings\Bruce> $c 1 2 3 PS C:\Documents and Settings\Bruce> $d = $c PS C:\Documents and Settings\Bruce> $d 1 2 3 PS C:\Documents and Settings\Bruce> $c[0]=99 PS C:\Documents and Settings\Bruce> $d 99 #<<< Hang on! I updated $c, not $d. is $d a reference to the same object as $c? 2 3 PS C:\Documents and Settings\Bruce> $c+=100 PS C:\Documents and Settings\Bruce> $d #if $d is a reference then 100 should appear on the end of this too... nup. 99 2 3 PS C:\Documents and Settings\Bruce> $c 99 2 3 100 PS C:\Documents and Settings\Bruce> Thanks in advance... BB. |
My System Specs![]() |
| | #2 (permalink) |
| | Re: Copying an array and weird things about updating arrays... On Aug 2, 2:30*am, bruce1313 <bruce1...@xxxxxx> wrote: Quote: > Hi, > I'm new to powershell and in my messing around I've found that array > assignments behave pretty interestingly. It would be great if someone could > explain 1/ the right way to do this and 2/ exactly why I'm seeing what I do... > > PS C:\Documents and Settings\Bruce> $c=1,2,3 > PS C:\Documents and Settings\Bruce> $c > 1 > 2 > 3 > PS C:\Documents and Settings\Bruce> $d = $c > PS C:\Documents and Settings\Bruce> $d > 1 > 2 > 3 > PS C:\Documents and Settings\Bruce> $c[0]=99 > PS C:\Documents and Settings\Bruce> $d * * > 99 * #<<< Hang on! I updated $c, not $d. is $d a reference to the same > object as $c? > 2 > 3 > PS C:\Documents and Settings\Bruce> $c+=100 > PS C:\Documents and Settings\Bruce> $d * *#if $d is a reference then 100 > should appear on the end of this too... nup. > 99 > 2 > 3 > PS C:\Documents and Settings\Bruce> $c > 99 > 2 > 3 > 100 > PS C:\Documents and Settings\Bruce> > > Thanks in advance... > BB. might be what is happening: When you do this: $d = $c $c and $d are both names for the same object. When you do $c += 100, this is essentially a shortcut for this: $c = $c + 100 This evaluates $c, adds 100 to the end, and then assigns the name $c to that result. So it looks like when you increase the length of an array, a new array object with the new length is created and assigned that name. It's possible that there's some other explanation, but I'm pretty sure that's what's going on. If you don't want them to both point to the same object then you can use the CopyTo() method of the array to copy the values, but it can be kind of a pain because the destination array needs to be the same size as the source, so alternatively you can do this: $d = $($c) That will evaluate $c and assign it to $d instead of assigning it to the same object. |
My System Specs![]() |
| | #3 (permalink) |
| | Re: Copying an array and weird things about updating arrays... Tojo is spot on, of course. I've inserted comments below - primarily on using hashcodes to help see how the underlying object changes. "tojo2000" <tojo2000@xxxxxx> wrote in message news:dcb014ca-6239-44ba-9ff2-e4ef5525cfd1@xxxxxx Quote: > On Aug 2, 2:30 am, bruce1313 <bruce1...@xxxxxx> > wrote: Quote: Quote: >> PS C:\Documents and Settings\Bruce> $c=1,2,3 Quote: Quote: >> PS C:\Documents and Settings\Bruce> $d = $c Quote: Quote: >> PS C:\Documents and Settings\Bruce> $c[0]=99 Quote: Quote: >> PS C:\Documents and Settings\Bruce> $d >> 99 #<<< Hang on! I updated $c, not $d. is $d a reference to the same >> object as $c? >> 2 >> 3 >> PS C:\Documents and Settings\Bruce> $c+=100 Quote: Quote: >> PS C:\Documents and Settings\Bruce> $d #if $d is a reference then 100 >> should appear on the end of this too... nup. >> 99 >> 2 >> 3 Quote: > When you do this: > > $d = $c > > $c and $d are both names for the same object. Quote: > When you do $c += 100, this is essentially a shortcut for this: > > $c = $c + 100 > > This evaluates $c, adds 100 to the end, and then assigns the name $c > to that result. > > So it looks like when you increase the length of an array, a new array > object with the new length is created and assigned that name. It's > possible that there's some other explanation, but I'm pretty sure > that's what's going on. to help check identity, like this. Note that $e has a distinct hashcode from $c and $d - it's just another object that happens to contain the same data. When an element of $c is updated, the hashcodes for $c and $d stay the same. As soon as the new element is added to $c, though, $c contains a new object - which has a new hashcode. PS> $c.GetHashCode() 7540993 PS> $d.GetHashCode() 7540993 PS> $e = 1,2,3 PS> $e.GetHashCode() 24062619 PS> $c[0] = 99 PS> $c.GetHashCode(),$d.GetHashCode() 7540993 7540993 PS> $c+=100 PS> $c.GetHashCode(),$d.GetHashCode() 66049492 7540993 Quote: > If you don't want them to both point to the same object then you can > use the CopyTo() method of the array to copy the values, but it can be > kind of a pain because the destination array needs to be the same size > as the source, so alternatively you can do this: > > $d = $($c) > > That will evaluate $c and assign it to $d instead of assigning it to > the same object. |
My System Specs![]() |
| | #4 (permalink) |
| | Re: Copying an array and weird things about updating arrays... PowerShell's array --arrayList and hashtable also-- assignment is done 'by reference'. Use the Clone Method to create a 'by value' copy of the same type array, hashTable or arrayList. tojo2000's workaround is very practical for untyped arrays but be aware that it casts the copy of the a typed array and the copy of a arrayList into an object[]. # array assignment $a1 = 1, 2, 3 $a2 = $a1 # <-- by reference write-host $a1[0] $a2[0] -f 10 -b 0 $a1[0] = '!' write-host $a1[0] $a2[0] -f 10 -b 0 # <-- $a2 is affected $a3 = $a1.clone() # <-- by value $a4 = $($a1) # <-- by value, only for array assignment write-host $a1[0] $a2[0] $a3[0] $a4[0] -f 10 -b 0 $a1[0] = '?' # $a2 is affected, while $a3 and $a4 aren't write-host $a1[0] $a2[0] $a3[0] $a4[0] -f 10 -b 0 1..4 | % {iex "`$a$_.getType().fullName"} # typed array assignment [int[]]$ia1 = 1, 2, 3 $ia2 = $ia1 # <-- by reference write-host $ia1[0] $ia2[0] -f 10 -b 0 $ia1[0] = 0 write-host $ia1[0] $ia2[0] -f 10 -b 0 # <-- $ia2 is affected $ia3 = $ia1.clone() # <-- by value $ia4 = $($ia1) # <-- by value, but not an [int[]] write-host $ia1[0] $ia2[0] $ia3[0] $ia4[0] -f 10 -b 0 $ia1[0] = 9 # $ia2 is affected, while $ia3 and $ia4 aren't write-host $ia1[0] $ia2[0] $ia3[0] $ia4[0] -f 10 -b 0 1..4 | % {iex "`$ia$_.getType().fullName"} # hashtable assignment $h1=@{} # empty hashtable $h1.one = 1 $h1.two = 2 $h1.three = 3 $h2 = $h1 # <-- by reference write-host $h1.one $h2.one -f 10 -b 0 $h1.one = '!' write-host $h1.one $h2.one -f 10 -b 0 # <-- $h2 is affected $h3 = $h1.clone() # <-- by value $h4 = $($h1) # <-- by reference write-host $h1.one $h2.one $h3.one $h4.one -f 10 -b 0 $h1.one = '?' # $h2 and $h4 are affected, while $h3 isn't write-host $h1.one $h2.one $h3.one $h4.one -f 10 -b 0 1..4 | % {iex "`$h$_.getType().fullName"} # arrayList $c1 = new-object System.Collections.ArrayList [void]$c1.Add(1) [void]$c1.Add(2) [void]$c1.Add(3) $c2 = $c1 # <-- by reference write-host $c1[0] $c2[0]-f 10 -b 0 $c1[0] = 0 write-host $c1[0] $c2[0] -f 10 -b 0 # <-- $c2 is affected $c3 = $c1.clone() # <-- by value $c4 = $($c1) # by value as an array though write-host $c1[0] $c2[0] $c3[0] $c4[0] -f 10 -b 0 $c1[0] = 9 # $c2 is affected; $c3 is not; $c4 elements not # affected but $c4 is an array not an arrayList write-host $c1[0] $c2[0] $c3[0] $c4[0] -f 10 -b 0 1..4 | % {iex "`$c$_.getType().fullName"} -- Kiron |
My System Specs![]() |
| | #5 (permalink) |
| | Re: Copying an array and weird things about updating arrays... Thanks everyone, all the responses have added to my understanding. So for a 2 dimensional array, I need to clone each of the 'rows'... #not like this... $x=(1,2),(3,4) $y = $x.Clone() $x.GetHashCode(),$y.GetHashCode() # <-- different $x[0].gethashcode(),$y[0].gethashcode() # <-- the same... #not by evaluating $x either - that gives the same result (except maybe data types might be different) #like this... for($i=0;$i -lt $x.length;$i++) { $z += ,($x[$i].clone()) } $x[0].gethashcode(),$z[0].gethashcode() 63876281 33271828 |
My System Specs![]() |
| | #6 (permalink) |
| | Re: Copying an array and weird things about updating arrays... On Aug 2, 4:29*pm, bruce1313 <bruce1...@xxxxxx> wrote: Quote: > Thanks everyone, all the responses have added to my understanding. > > So for a 2 dimensional array, I need to clone each of the 'rows'... > > #not like this... > *$x=(1,2),(3,4) > *$y = $x.Clone() > *$x.GetHashCode(),$y.GetHashCode() * # <-- different > *$x[0].gethashcode(),$y[0].gethashcode() * # <-- the same... > > #not by evaluating $x either - that gives the same result (except maybe data > types might be different) > > #like this... > for($i=0;$i -lt $x.length;$i++) { > * *$z += ,($x[$i].clone()) > > } > > $x[0].gethashcode(),$z[0].gethashcode() > 63876281 > 33271828 doozy. Here's a workaround that should work for you. It works for arrays only. function New-Hashcode($var) { if ($var.GetType().Name -eq 'Object[]) { $var += 0 $var = $var[0..($var.Length - 2)] foreach($index in (0..($var.Length -1))) { $var[$index] = New-Hashcode $var[$index] } } return $var } PS C:\> $y = New-Hashcode($x) PS C:\> $x.GetHashCode() 5696624 PS C:\> $y.GetHashCode() 27443610 PS C:\> $x[0].GetHashCode() 41883196 PS C:\> $y[0].GetHashCode() 35846188 Oddly enough it doesn't work for strings, but here's another workaround for strings: $newstring = $string.Split('') |
My System Specs![]() |
| | #7 (permalink) |
| | Re: Copying an array and weird things about updating arrays... You got it Bruce. But what you're copying is a nested array, not a multi-dimensional array. To copy a multi-dimensional array 'by value' use the Clone Method. To copy a one level nested _array of arrays_ --or nested arrays-- 'by value' and keep the arrays' type, clone the innermost arrays. You can use the pipeline to simplify the process and avoid the For Loop. For a one level nested array is pretty simple, but it gets trickier as the nested level increases. # multi-dimensional arrays # 3D string array $x = new-object 'string[,,]' 2,2,2 $x[0,0,0] = 'number 1' $x[0,0,1] = 'number 2' $x[0,1,0] = 'number 3' $x[0,1,1] = 'number 4' $x[1,0,0] = 'number 5' $x[1,0,1] = 'number 6' $x[1,1,0] = 'number 7' $x[1,1,1] = 'number 8' $y = $x.clone() write-host Before $x[0,0,0] $y[0,0,0] -f 11 -b 0 $x[0,0,0] = 'number 13' write-host After $x[0,0,0] $y[0,0,0] -f 10 -b 0 # array type is maintained write-host $x.getType().name $y.getType().name # different objects write-host $x.getHashCode() $y.getHashCode() # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # # array of arrays, or nested arrays rv x,y -ea 0 $x = [byte[]](1,2),[uInt16[]](3,4) $y = $x | % {,$_.clone()} write-host Before $x[0][0] $y[0][0] -f 11 -b 0 $x[0][0] = 13 write-host After $x[0][0] $y[0][0] -f 10 -b 0 # array types are maintained 0..1 | % {write-host $x[$_].getType().name $y[$_].getType().name} # different objects 0..1 | % {write-host $x[$_].getHashCode() $y[$_].getHashCode()} # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # rv x, y -ea 0 $x = ([int[]](1,2),[long[]](3,4)),([decimal[]](5,6),[double[]](7,8)) $y = $x | % {$x1 = $_ | % {,$_.clone()}; ,$x1; rv x1} write-host Before $x[0][0][0] $y[0][0][0] -f 11 -b 0 $x[0][0][0] = 13 write-host After $x[0][0][0] $y[0][0][0] -f 10 -b 0 # array types are maintained 0..1 | % {$i = $_; 0..1 | % { write-host $x[$i][$_].getType().name $y[$i][$_].getType().name } } # different objects 0..1 | % {$i = $_; 0..1 | % { write-host $x[$i][$_].getHashCode() $y[$i][$_].getHashCode() } } -- Kiron |
My System Specs![]() |
| | #8 (permalink) |
| | Re: Copying an array and weird things about updating arrays... On Aug 3, 2:01*am, tojo2000 <tojo2...@xxxxxx> wrote: Quote: > On Aug 2, 4:29*pm, bruce1313 <bruce1...@xxxxxx> > wrote: > > > Quote: > > Thanks everyone, all the responses have added to my understanding. Quote: > > So for a 2 dimensional array, I need to clone each of the 'rows'... Quote: > > #not like this... > > *$x=(1,2),(3,4) > > *$y = $x.Clone() > > *$x.GetHashCode(),$y.GetHashCode() * # <-- different > > *$x[0].gethashcode(),$y[0].gethashcode() * # <-- the same... Quote: > > #not by evaluating $x either - that gives the same result (except maybedata > > types might be different) Quote: > > #like this... > > for($i=0;$i -lt $x.length;$i++) { > > * *$z += ,($x[$i].clone()) Quote: > > } Quote: > > $x[0].gethashcode(),$z[0].gethashcode() > > 63876281 > > 33271828 > I have to say, I'm glad you ran into this before I did, because it's a > doozy. > > Here's a workaround that should work for you. *It works for arrays > only. > > function New-Hashcode($var) { > * if ($var.GetType().Name -eq 'Object[]) { > * * $var += 0 > * * $var = $var[0..($var.Length - 2)] > > * * foreach($index in (0..($var.Length -1))) { > * * * $var[$index] = New-Hashcode $var[$index] > * * } > * } > > * return $var > > } > > PS C:\> $y = New-Hashcode($x) > PS C:\> $x.GetHashCode() > 5696624 > PS C:\> $y.GetHashCode() > 27443610 > PS C:\> $x[0].GetHashCode() > 41883196 > PS C:\> $y[0].GetHashCode() > 35846188 > > Oddly enough it doesn't work for strings, but here's another > workaround for strings: > > $newstring = $string.Split('') there to be used as the identity, or is it just so unique that it can be used for that. I tried looking it up on MSDN but all I found out is that GetHashCode() is overridden for PSObject. |
My System Specs![]() |
![]() |
| Thread Tools | |
| |
Similar Threads | ||||
| Thread | Forum | |||
| associative array of associative arrays | PowerShell | |||
| Weird things in User folder. | Vista file management | |||
| copying files referenced in an array...help? | PowerShell | |||
| Newbie question - Copying files listed in an array | PowerShell | |||
| Hashtable with array as a key .... weird behaviour | PowerShell | |||