Welcome › Forums › General PowerShell Q&A › Creating nested data structure
- This topic has 3 replies, 4 voices, and was last updated 1 week, 3 days ago by
Participant.
-
AuthorPosts
-
-
January 5, 2021 at 6:40 am #284242
Hi all
I have a string like ‘A/B/C’ that I’m trying to get into a nested structure like the following:
PowerShell12345678910111213141516$folders = @(@{Name = 'A'Folders = @(@{Name = 'B'Folders = @(@{Name = 'C'Folders = @()})})})I thought this would be pretty straightforward using recursion, but only the top-level hashtable (“A”) gets added to $bar…
PowerShell123456789101112131415161718192021222324252627function Foo {param ([Parameter()][string[]]$Path,[Parameter()][hashtable[]][ref]$Folders)if (!$Path) {return}$current, $children = $Path$Folders.Value += @{Name = $currentFolders = @()}Foo $children ([ref]$Folders.Value[-1].Folders)}$bar = @()Foo 'A/B/C'.Split('/') ([ref]$bar)Any ideas? Must be some issue with passing by ref the deeper array?
Note I have an array of strings like ‘A/B/C’ (e.g. ‘A/B/D’, ‘D/E/F) to add to the structure, but that should be easy once I get past this first issue…
-
January 5, 2021 at 8:58 am #284254
Here is one way, build it backwards:
PowerShell123456789101112$arr = 'A','B','C','D','E','F','G'[array]::Reverse($arr)$lastObj = $nullforeach ($item in $arr) {$lastObj = [pscustomobject]@{Name = $itemFolders = @($lastObj)}}$lastObj | ConvertTo-Json -Depth 30 -
January 5, 2021 at 10:52 am #284272
Wow this was a fun exercise. Haven’t messed with recursion much since my freshman year at college. I created a recursive function that will create the data structure you want.
PowerShell123456789101112function folders([System.Collections.ArrayList]$Name, $ht = @{}) {$ht.name = $Name[0]if ($Name.count -eq 1) {$ht.folders = @(); $ht} #base caseelse {$Name.RemoveAt(0)$ht.folders = @(folders -ht $ht.Clone() -Name $Name)$ht #recurse case} #else} #function$TestData = @("A/B/C","D/E/F")$Result = $TestData | ForEach-Object {folders -Name @($_ -split "/")} -
January 8, 2021 at 5:28 pm #284890
I like using a Stack object for this exercise:
PowerShell12345678910$folders = 'a/b/c','d/e/f' | Foreach-Object {[system.collections.stack]$stack = $_ -split '/' | Foreach-Object {[ordered]@{name = $_; folders = @()}}while ($stack.Count -gt 1) {$stack.ToArray()[1].Folders = ,$stack.Pop()}$stack}Remove-Variable stack
-
-
AuthorPosts
- You must be logged in to reply to this topic.