Avoiding Smoothing Agnostic Jagged Array in Powershell

I am having an interesting problem in Powershell and I could not find a solution for it. When I google (and find things like this post ), nothing special like what I'm trying to do appears, so I decided to post the question here.

The problem is with multidimensional arrays with the length of the external array. Powershell seems to be very categorical about smoothing arrays such as @( @('A') ) becomes @( 'A' ) . Here is the first snippet (prompt is>, btw):

 > $a = @( @( 'Test' ) ) > $a.gettype().isarray True > $a[0].gettype().isarray False 

So, I would like to have $a[0].gettype().isarray true so that I can index the value as $a[0][0] (the real world script processes dynamic arrays inside the loop, and I would like to get the values ​​as $a[$i][$j] , but if the internal element is not recognized as an array, but as a string (in my case), you start indexing into string characters, as in $a[0][0] -eq 'T' ).

I have some examples with long codes, so I posted them at the end. And, for reference, this is on Windows 7 Ultimate with PSv2 and PSCX installed.

Consider code example 1 . I create a simple array manually using the + = operator. The intermediate array $w smoothed and therefore is not added to the final array correctly. I found solutions online for similar problems, which are mainly related to the comma in front of the internal array, to make the external array not smooth, which works, but again I am looking for a solution that can create arrays inside the loop (array from array of arrays, CSS file processing ), so if I add a leading comma to an array of single elements (implemented as an intermediate array of $y ), I would like to do the same for other arrays (e.g. $z ), but this negatively affects how $z is added to the final array.

Now consider code example 2 . This is closer to the actual problem I am having. When a multidimensional array with one element returns from a function, it is smoothed. This is correct before he leaves the function. And again, these are examples, I'm really trying to process the file without knowing whether the function will return using @( @( 'color', 'black') ) or using @( @( 'color', 'black'), @( 'background-color', 'white') )

Has anyone come across this, and has anyone solved this? I know that I can create infrastructure objects, and I assume that everything will be fine if I create an object [] or a list <> or something else like that, but I dealt with this a bit and something seems to be due be the right way to do this (without having to instantiate true frameworks).

Code Example 1

 function Display($x, [int]$indent, [string]$title) { if($title -ne '') { write-host "$title`: " -foregroundcolor cyan -nonewline } if(!$x.GetType().IsArray) { write-host "'$x'" -foregroundcolor cyan } else { write-host '' $s = new-object string(' ', $indent) for($i = 0; $i -lt $x.length; $i++) { write-host "$s[$i]: " -nonewline -foregroundcolor cyan Display $x[$i] $($indent+1) } } if($title -ne '') { write-host '' } } ### Start Program $final = @( @( 'a', 'b' ), @('c')) Display $final 0 'Initial Value' ### How do we do this part ??? ########### ## $w = @( @('d', 'e') ) ## $x = @( @('f', 'g'), @('h') ) ## # But now $w is flat, $w.length = 2 ## ## ## # Even if we put a leading comma (,) ## # in front of the array, $y will work ## # but $w will not. This can be a ## # problem inside a loop where you don't ## # know the length of the array, and you ## # need to put a comma in front of ## # single- and multidimensional arrays. ## $y = @( ,@('D', 'E') ) ## $z = @( ,@('F', 'G'), @('H') ) ## ## ## ########################################## $final += $w $final += $x $final += $y $final += $z Display $final 0 'Final Value' ### Desired final value: @( @('a', 'b'), @('c'), @('d', 'e'), @('f', 'g'), @('h'), @('D', 'E'), @('F', 'G'), @('H') ) ### As in the below: # # Initial Value: # [0]: # [0]: 'a' # [1]: 'b' # [1]: # [0]: 'c' # # Final Value: # [0]: # [0]: 'a' # [1]: 'b' # [1]: # [0]: 'c' # [2]: # [0]: 'd' # [1]: 'e' # [3]: # [0]: 'f' # [1]: 'g' # [4]: # [0]: 'h' # [5]: # [0]: 'D' # [1]: 'E' # [6]: # [0]: 'F' # [1]: 'G' # [7]: # [0]: 'H' 

Code Example 2

 function Display($x, [int]$indent, [string]$title) { if($title -ne '') { write-host "$title`: " -foregroundcolor cyan -nonewline } if(!$x.GetType().IsArray) { write-host "'$x'" -foregroundcolor cyan } else { write-host '' $s = new-object string(' ', $indent) for($i = 0; $i -lt $x.length; $i++) { write-host "$s[$i]: " -nonewline -foregroundcolor cyan Display $x[$i] $($indent+1) } } if($title -ne '') { write-host '' } } function funA() { $ret = @() $temp = @(0) $temp[0] = @('p', 'q') $ret += $temp Display $ret 0 'Inside Function A' return $ret # What about return ,$ret ? What about if $ret = @( @('p', 'q'), @('r', 's') ) -- would return ,$ret still work? } function funB() { $ret = @( ,@('r', 's') ) Display $ret 0 'Inside Function B' return $ret } ### Start Program $z = funA Display $z 0 'Return from Function A' $z = funB Display $z 0 'Return from Function B' ### Desired final value: @( @('p', 'q') ) and same for r,s ### As in the below: # # Inside Function A: # [0]: # [0]: 'p' # [1]: 'q' # # Return from Function A: # [0]: # [0]: 'p' # [1]: 'q' 

Thanks Matt

+4
source share
2 answers

There is another question that starts with the same problem: Powershell Traps . This seems to be done by design.

I think if you return ,$ret instead of $ret , it should work.

Two more notes:

  • you can check if the item is an array of $item -is [array] (just because it is more like PowerShell;)
  • @() only affects elements that are not arrays. If you bind @(@(@(1))) , you get an array with one element int ( @(@(@(1)))[0].gettype() returns Int32).
    So @( ,@('r', 's') ) same as ,@('r', 's') .
+5
source

I tried what stej said and it worked using this example:

 function funC([int]$numOfPairs) { $ret = @() if($numOfPairs -eq 1) { $ret = ,@('r','s') } elseif($numOfPairs -eq 2) { $ret = @('r','s'),@('t','u') } else { $ret = @('r','s'),@('t','u'),@('v','w') } Display $ret 0 "Inside Function C ($numOfPairs)" return ,$ret } ### Start Program $z = funC 1 Display $z 0 'Return from Function C(1)' $z = funC 2 Display $z 0 'Return from Function C(2)' $z = funC 3 Display $z 0 'Return from Function C(3)' 
0
source

Source: https://habr.com/ru/post/1304371/


All Articles