Page 1 of 1

ArrayList of ArrayLists

Posted: Thu Aug 08, 2019 7:52 am
by azeiler
I've got an ArrayList of ArrayLists of Strings that I need to process with an advanced function. I am modeling that function off of what I learned in "Learn Powershell Toolmaking in a Month of Lunches."

In order to make the functions flexible, they tell you in that book to set it up so that a parameter can be piped in, but also taken as an array. So basically, you make the advanced function to accept ValuesFromPipeline for a particular parameter, but then you also make that parameter type an array and add a ForEach-Object in your Process.

What I am running into is that if I configure my function this way, it no longer works to pipe the values in. Because then it treats them one at a time, and the ForEach-Object breaks that ArrayList into its subsequent strings for processing. Is there an easy way to prevent this?

See code example below. When I pass $OutsideArray to Get-Data as a normal parameter (Get-Data $OutsideArray), it works. When I remove the ForEach-Object in the function, it works. But when I pipe $OutsideArray in as is, it no longer works.
  1. function Get-Data()
  2.  
  3. {
  4.  
  5.     [CmdletBinding()]
  6.  
  7.     param (
  8.  
  9.         [Parameter(Mandatory = $True, ValueFromPipeline = $True)]
  10.  
  11.         [System.Collections.ArrayList]$ModuleBlocks
  12.  
  13.     )
  14.  
  15.    
  16.  
  17.     BEGIN
  18.  
  19.     {
  20.  
  21.     }
  22.  
  23.     PROCESS
  24.  
  25.     {
  26.  
  27.         $ModuleBlocks | %{
  28.  
  29.            
  30.  
  31.             $test = $_
  32.  
  33.  
  34.  
  35.         }
  36.  
  37.        
  38.  
  39.     }
  40.  
  41.     END { }
  42.  
  43.    
  44.  
  45. }
  46.  
  47.  
  48.  
  49. $OutsideArray = New-Object System.Collections.ArrayList
  50.  
  51.  
  52.  
  53. For ($i = 0; $i -lt 10; $i++)
  54.  
  55. {
  56.  
  57.    
  58.  
  59.     $InsideArray = New-Object System.Collections.ArrayList
  60.  
  61.    
  62.  
  63.     For ($j = 0; $j -le 10; $j++)
  64.  
  65.     {
  66.  
  67.         $InsideArray.Add("$i This is a test $j") | Out-Null
  68.  
  69.     }
  70.  
  71.    
  72.  
  73.     $OutsideArray.Add($InsideArray) | Out-Null
  74.  
  75.    
  76.  
  77. }
  78.  
  79.  
  80.  
  81. $OutsideArray | Get-Data

Re: ArrayList of ArrayLists

Posted: Thu Aug 08, 2019 9:32 am
by jvierra
The enumerator will enumerate the array in a pipeline. That is expected. How you design this depends on the intended use. I suggest gaining more experience with PowerShell and Advanced Functions before trying to do this. When yu have a real-world example then you will be able to ask a question that can be answered.

Run the following to see what is happening:

Code: Select all

function Get-Data() {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $True, ValueFromPipeline = $True)]
        [System.Collections.ArrayList]$ModuleBlocks
    )
    begin {
        Write-Host 'Begin called'
    }
    process {
        Write-Host 'Process called' -Fore green
        $ModuleBlocks | 
            ForEach-Object{
                Write-Host "`t`tForeach loop" -Fore Yellow
                $test = $_
            }
    }
    end {
        Write-Host 'Begin called'
    }
}

$OutsideArray = New-Object System.Collections.ArrayList
For ($i = 0; $i -lt 10; $i++) {  
    $InsideArray = New-Object System.Collections.ArrayList
    For ($j = 0; $j -le 10; $j++) {
        $InsideArray.Add("$i This is a test $j") | Out-Null
    }
    $OutsideArray.Add($InsideArray) | Out-Null
}

$OutsideArray | Get-Data 

Re: ArrayList of ArrayLists

Posted: Thu Aug 08, 2019 9:35 am
by jvierra
This may make it more obvious.

Code: Select all


$OutsideArray = New-Object System.Collections.ArrayList
For ($i = 0; $i -lt 10; $i++) {  
    $InsideArray = New-Object System.Collections.ArrayList
    For ($j = 0; $j -le 10; $j++) {
        $InsideArray.Add("$i This is a test Outer: $i Inner: $j") | Out-Null
    }
    $OutsideArray.Add($InsideArray) | Out-Null
}

$OutsideArray | Get-Data