2016-07-31 72 views
0

我想在此腳本中使用$a變量來處理中間步驟,以便我不必重複使用$array[$array.Count-1]。同樣,對於$prop也是如此。但是,值將被循環中的最後一個值覆蓋。使用中間變量處理數組(參考類型)

$guests = Import-Csv -Path C:\Users\shant_000\Desktop\UploadGuest_test.csv 
$output = gc '.\Sample Json.json' | ConvertFrom-Json 
$array = New-Object System.Collections.ArrayList; 

foreach ($g in $guests) { 
    $array.Add($output); 
    $a = $array[$array.Count-1]; 

    $a.Username = $g.'EmailAddress'; 
    $a.DisplayName = $g.'FirstName' + ' ' + $g.'LastName'; 
    $a.Password = $g.'LastName' + '123'; 
    $a.Email = $g.'EmailAddress'; 

    foreach ($i in $a.ProfileProperties.Count) { 
     $j = $i - 1; 

     $prop = $a.ProfileProperties[$j]; 

     if ($prop.PropertyName -eq "FirstName") { 
      $prop.PropertyValue = $g.'FirstName'; 
     } elseif ($prop.PropertyName -eq "LastName") { 
      $prop.PropertyValue = $g.'LastName'; 
     } 

     $a.ProfileProperties[$j] = $prop; 
    } 

    $array[$array.Count-1] = $a; 
} 

$array; 
+1

'$ output = gc'。\ Sample Json.json'| ConvertFrom-Json' - >'$ outputJson = gc'。\ Sample Json.json'','$ array.Add($ output)' - >'[void] $ array.Add(($ outputJson | ConvertFrom-Json) )' – PetSerAl

回答

0

所有的數組元素被引用一個實際的變量:$output

通過重複JSON的解析創建一個全新的對象的每個時間:

$jsontext = gc '.\Sample Json.json' 
.......... 
foreach ($g in $guests) { 
    $a = $jsontext | ConvertFrom-Json 

    # process $a 
    # ............ 

    $array.Add($a) >$null 
} 

如果JSON文件是非常大的,你改變它只有很少的部件可以使用在更快的克隆技術修改的部分(和他們的整個父鏈)通過.PSObject.Copy()

foreach ($g in $guests) { 
    $a = $output.PSObject.Copy() 
    # ............ 

    $a.ProfileProperties = $a.ProfileProperties.PSObject.Copy() 
    # ............ 
    foreach ($i in $a.ProfileProperties.Count) { 
     # ............ 
     $prop = $a.ProfileProperties[$j].PSObject.Copy(); 
     # ............ 
    } 

    $array.Add($a) >$null 
} 
+0

另請參見:[在Powershell中,如何通過「value」而不是「reference」來存儲一個對象?](http://stackoverflow.com/a/18036823) – wOxxOm

+0

您確定'。 PSObject.Copy()'會在OP情況下做足夠深的克隆嗎? – PetSerAl

+0

你說得對。編輯。 – wOxxOm

0

正如其他人所指出的那樣,附加$object追加到同一個對象的引用,讓你不斷改變的值在日的所有元素列表。不幸的是,建議的方法@wOxxOm(如果你的JSON數據結構具有嵌套對象,那麼我認爲最初會起作用)不起作用,因爲Copy()只克隆最頂層的對象,而嵌套的對象仍然引用它們的原始對象。

示範:

PS C:\>$o = '{"foo":{"bar":42},"baz":23}' | ConvertFrom-Json 
PS C:\>$o | Format-Custom * 

class PSCustomObject 
{ 
    foo = 
    class PSCustomObject 
    { 
     bar = 42 
    } 
    baz = 23 
} 

PS C:\>$o1 = $o 
PS C:\>$o2 = $o.PSObject.Copy()

如果你改變這兩個$o1$o2嵌套屬性bar它已經在這兩個對象最後一組,這是其中的任何值:

PS C:\>$o1.foo.bar = 23 
PS C:\>$o2.foo.bar = 24 
PS C:\>$o1.foo.bar 
24 
PS C:\>$o2.foo.bar 
24

只有當您更改最上面的對象的屬性,您將得到$o1$o2之間的差異:

PS C:\>$o1.baz = 5 
PS C:\>$o.baz 
5 
PS C:\>$o1.baz 
5 
PS C:\>$o2.baz 
23

雖然你可以做一個deep copy它不像人們想的那樣簡單直接。通常情況下,您只需要花費較少的精力(簡單的代碼)就可以多次創建該對象,如@PetSerAl在您的問題的評論中所建議的那樣。

我也建議避免在循環中追加到數組(或arraylist)。你可以簡單地附和你的對象內環路和分配環路變量收集爲列表/陣列的整個輸出:

$json = Get-Content '.\Sample Json.json' -Raw 
$array = foreach ($g in $guests) { 
    $a = $json | ConvertFrom-Json # create new object 

    $a.Username = $g.'EmailAddress' 
    ... 

    $a # echo object, so it can be collected in $array 
} 

上的PowerShell v3的使用Get-Content -Raw和更新(或Get-Content | Out-String在較早版本),以避免JSON文件中的多行JSON數據問題。