h41msh1c0r
Goto Top

Powershell New-Object meckert Property an, Verständnisfrage

Aloa,

ausgehend vom letzten Beitrag:
Powershell Daten strukturieren als json

Wollte ich das das Ganze nun in Schleifen packen.

$SubscriptionSet = ("Subscription1","Subscription2","Subscription3")  
$years = ("2020","2021","2022","2023","2024","2025")  

$allData = @()

$SubscriptionSet | %{

    Write-Host $_

    $allData += New-Object PSObject -Property @{"$_" = @()}  

    $($allData).("$_") += New-Object PSObject -Property @{Count=''; Status=@(); Ordered=@(); Modified=@(); Cancelled=@()}  

}

$allData | ConvertTo-Json

$($allData).("Subscription1")  


Ergebnis:

Subscription1
Subscription2
The property 'Subscription2' cannot be found on this object. Verify that the property exists and can be set.  
At line:16 char:7
+     $($allData).("$_") += New-Object PSObject -Property @{Count=''; S ...  
+       ~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : PropertyAssignmentException
 
Subscription3
The property 'Subscription3' cannot be found on this object. Verify that the property exists and can be set.  
At line:16 char:7
+     $($allData).("$_") += New-Object PSObject -Property @{Count=''; S ...  
+       ~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : PropertyAssignmentException
 
[
    {
        "Subscription1":  [  
                              "@{Ordered=System.Object[]; Status=System.Object[]; Cancelled=System.Object[]; C  
ount=; Modified=System.Object[]}"  
                          ]
    },
    {
        "Subscription2":  [  

                          ]
    },
    {
        "Subscription3":  [  

                          ]
    }
]

Ordered   : {}
Status    : {}
Cancelled : {}
Count     : 
Modified  : {}

Warum stört er sich ab Runde 2 an der Property, wenn er das New-Object im ersten Lauf sauber gemacht hat?
Das "$_" ist ja pro Durchlauf korrekt gefüllt und wenn er beim ersten Lauf $alldata ein neues Objekt verpasst hat
warum dann nicht im Durchlauf 2 und 3?

VG

Content-ID: 667941

Url: https://administrator.de/contentid/667941

Ausgedruckt am: 21.11.2024 um 12:11 Uhr

14260433693
Lösung 14260433693 06.09.2024 aktualisiert um 14:04:37 Uhr
Goto Top
$SubscriptionSet = "Subscription1","Subscription2","Subscription3"  
$alldata = [ordered]@{}
foreach($subscription in $SubscriptionSet){
    $alldata.$subscription = [ordered]@{Count=''; Status=@(); Ordered=@(); Modified=@(); Cancelled=@()}  
}
$allData | ConvertTO-JSON
$allData.Subscription1
$allData.Subscription2
$allData.Subscription3
Gruß
TK1987
Lösung TK1987 06.09.2024 um 13:57:51 Uhr
Goto Top
Moin,

Zitat von @H41mSh1C0R:
Warum stört er sich ab Runde 2 an der Property, wenn er das New-Object im ersten Lauf sauber gemacht hat?
weil du versuchst, Eigenschaften innerhalb eines Arrays zuzuweisen. Das funktioniert jedoch nur, wenn alle Objekte im Array diese Eigenschaft auch tatsächlich besitzen.
Dies ist aber nur beim ersten Durchlauf der Fall.

Gruß Thomas
H41mSh1C0R
H41mSh1C0R 06.09.2024 um 14:07:44 Uhr
Goto Top
Danke =)

$years           = ("2020","2021","2022","2023","2024","2025")  
$SubscriptionSet = ("Subscription1","Subscription2","Subscription3")  
$Status          = ("Active", "Cancelled")  
$alldata         = @{}

$SubscriptionSet | %{
    $alldata.$_ = [ordered]@{Count=''; Status=@(); Ordered=@(); Modified=@(); Cancelled=@()}    

    $zwischenschritt = $alldata.$_

    $years | %{
        $($zwischenschritt).Ordered    += [ordered]@{$_=''}    
        $($zwischenschritt).Modified   += [ordered]@{$_=''}    
        $($zwischenschritt).Cancelled  += [ordered]@{$_=''}    
    }

    $status | %{
        $($zwischenschritt).Status     += [ordered]@{$_=''}    
    }
}

$allData."Subscription1".("Active") = 10  
  
$allData | ConvertTo-Json -Depth 3

Das Ganze adaptiert und das Ergebnis schaut so aus wie ich das gern hätte. =)
H41mSh1C0R
H41mSh1C0R 06.09.2024 um 14:08:06 Uhr
Goto Top
Das leuchtet ein. =) Danke
14260433693
14260433693 06.09.2024 aktualisiert um 14:50:40 Uhr
Goto Top
Den Operator += sollte man bei simplen Arrays wo es geht immer vermeiden, denn das ist assembler technisch immer sehr aufwendig da dabei die Variable immer wieder neu angelegt werden muss, und der Speicher der Variablen für den neuen Inhalt neu alloziiert werden muss damit das neue Element hinein passt. In Schleifen ist das besonders ineffizient.
Besser man weist den finalen Inhalt der Eigenschaft direkt in einem Rutsch zu.

Beispiel:

Das hier
$result = foreach($item in $items){
   $item
}
ist effizienter als diese Konstrukte hier
$result = @()
foreach($item in $items){
   $result += $item
}
Foreach-Object (%{}) ist ebenfalls wesentlich langsamer als Foreach.
H41mSh1C0R
H41mSh1C0R 06.09.2024 um 15:04:26 Uhr
Goto Top
$stopwatch =  [system.diagnostics.stopwatch]::StartNew()

$years           = ("2020","2021","2022","2023","2024","2025")  
$SubscriptionSet = ("Subscription1","Subscription2","Subscription3")  
$Status          = ("Active", "Cancelled")  
$alldata         = @{}

$SubscriptionSet | %{
    $alldata.$_ = [ordered]@{Count=''; Status=@(); Ordered=@(); Modified=@(); Cancelled=@()}    

    $zwischenschritt = $alldata.$_

    $years | %{
        $($zwischenschritt).Ordered    += [ordered]@{$_=''}    
        $($zwischenschritt).Modified   += [ordered]@{$_=''}    
        $($zwischenschritt).Cancelled  += [ordered]@{$_=''}    
    }

    $status | %{
        $($zwischenschritt).Status     += [ordered]@{$_=''}    
    }
}
$stopwatch.Stop()
Write-Host $stopwatch.Elapsed

00:00:00.0208472


$stopwatch =  [system.diagnostics.stopwatch]::StartNew()

$years           = ("2020","2021","2022","2023","2024","2025")  
$SubscriptionSet = ("Subscription1","Subscription2","Subscription3")  
$Status          = ("Active", "Cancelled")  
$alldata         = @{}

foreach ($subscription in $SubscriptionSet){

    $alldata.$subscription = [ordered]@{Count=''; Status=@(); Ordered=@(); Modified=@(); Cancelled=@()}    

    $zwischenschritt = $alldata.$subscription 

    foreach($yr in $years){
        $($zwischenschritt).Ordered    = $($zwischenschritt).Ordered    + [ordered]@{$yr=''}    
        $($zwischenschritt).Modified   = $($zwischenschritt).Modified   + [ordered]@{$yr=''}    
        $($zwischenschritt).Cancelled  = $($zwischenschritt).Cancelled  + [ordered]@{$yr=''}    
    }

    foreach($stat in $status){
        $($zwischenschritt).Status   = $($zwischenschritt).Status    + [ordered]@{$stat=''}    
    }
}

$stopwatch.Stop()
Write-Host $stopwatch.Elapsed

00:00:00.0007732

!!!!Wahnsinn!!!!

Würde man die inneren foreach auch noch wegoptimiert bekommen, weil das Set an Properties in Ordered, Modified und Cancelled ist ja immer gleich. Also jeweils die Jahreszahlen.

"Subscription2":  {  
                          "Count":  "",  
                          "Status":  [  
                                         {
                                             "Active":  ""  
                                         },
                                         {
                                             "Cancelled":  ""  
                                         }
                                     ],
                          "Ordered":  [  
                                          {
                                              "2020":  ""  
                                          },
                                          {
                                              "2021":  ""  
                                          },
                                          {
                                              "2022":  ""  
                                          },
                                          {
                                              "2023":  ""  
                                          },
                                          {
                                              "2024":  ""  
                                          },
                                          {
                                              "2025":  ""  
                                          }
                                      ],
                          "Modified":  [  
                                           {
                                               "2020":  ""  
                                           },
                                           {
                                               "2021":  ""  
                                           },
                                           {
                                               "2022":  ""  
                                           },
                                           {
                                               "2023":  ""  
                                           },
                                           {
                                               "2024":  ""  
                                           },
                                           {
                                               "2025":  ""  
                                           }
                                       ],
                          "Cancelled":  [  
                                            {
                                                "2020":  ""  
                                            },
                                            {
                                                "2021":  ""  
                                            },
                                            {
                                                "2022":  ""  
                                            },
                                            {
                                                "2023":  ""  
                                            },
                                            {
                                                "2024":  ""  
                                            },
                                            {
                                                "2025":  ""  
                                            }
                                        ]
                      }
14260433693
Lösung 14260433693 06.09.2024 um 15:37:27 Uhr
Goto Top
Würde man die inneren foreach auch noch wegoptimiert bekommen, weil das Set an Properties in Ordered, Modified und Cancelled ist ja immer gleich. Also jeweils die Jahreszahlen.

$years           = [ordered]@{"2020"='';"2021"='';"2022"='';"2023"='';"2024"='';"2025"=''}  
$SubscriptionSet = "Subscription1","Subscription2","Subscription3"  
$Status          = [ordered]@{"Active"='';"Cancelled"=''}   
$alldata         = @{}

foreach ($subscription in $SubscriptionSet){
    $alldata.$subscription = [ordered]@{
        Count=''  
        Status=$Status
        Ordered=$years
        Modified=$years
        Cancelled=$years
    }
}
H41mSh1C0R
H41mSh1C0R 06.09.2024 aktualisiert um 15:46:02 Uhr
Goto Top
Danke =)

00:00:00.0000951

face-smile face-smile face-smile