PowerShell: Split Array into Multiple Sub-Arrays and Inflate Strings to Certain Lengths to Create Visual Columns

What does a nerd do on his free time? Give himself little puzzles to solve. Today’s problem I’ve given myself is to demonstrate PS techniques to manipulate an array of integers: (a) split that array into multiple sub-arrays and (b) display a ‘squarish’ output of a string blob where its height and width are similar. The enclosing function below illustrates the querying of my local PC for currently opened ports.

function displayArrayAsColumns($array){   
    function inflateString([string]$string="test",[int]$maxInflate=6,[string]$fillWith=' '){
        [int]$difference=$maxInflate-$string.tostring().Length
        if($difference -gt 0){        
            [string]$fill=$fillWith*$difference
            return $string+$fill
            }    
    }
    $columnWidth=.{return ($array[$array.length-1]).tostring().Length+1}
    $numberOfElements=$array.Count
    $numberOfRows=[math]::Ceiling(($numberOfElements+$columnWidth)/4)
    $splittedArray=@()
    $fragment=[math]::Ceiling($numberOfElements/$numberOfRows)
    $array=$array|%{inflateString $_ $columnWidth}
    for ($i=0;$i -lt $numberOfRows; $i++){                       
        $endIndex=($fragment*($i+1))-1;
        $startIndex=$endIndex-$fragment+1;
        if($i -eq $columns-1){$endIndex=$elementsCount-1}
        #write-host "startIndex: $startIndex | endIndex: $endIndex";   
        $splittedArray+=,$array[$startIndex..$endIndex];
        }
    return ($splittedArray|%{$_ -join ''} | out-string).trim()
}
function listPortsInUse{
    param(
        $maxPortNumber=65535
    )
    function splitArray{
        param($array,[int]$columns=5)
        $splittedArray=@()        
        $elementsCount=$array.Length
        $fragment=[math]::Ceiling($elementsCount/$columns)
        for ($i=0;$i -lt $columns; $i++){                       
            $endIndex=($fragment*($i+1))-1;
            $startIndex=$endIndex-$fragment+1;
            if($i -eq $columns-1){$endIndex=$elementsCount-1}
            #write-host "startIndex: $startIndex | endIndex: $endIndex";   
            $splittedArray+=,$array[$startIndex..$endIndex];
            }
        return $splittedArray    
    }

    function inflateString([string]$string="test",[int]$maxInflate=6,[string]$fillWith=' '){
        [int]$difference=$maxInflate-$string.tostring().Length
        if($difference -gt 0){        
            [string]$fill=$fillWith*$difference
            return $string+$fill
            }    
    }

    $netstat=netstat -aon
    $portsInUse=$netstat|%{
                        [void]($_ -match "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:(\d{1,5})");
                        try{[int]$port=$matches[1]}catch{$port=0}
                        if($port -gt 0 -and $port -lt $maxPortNumber){$port}
                        }|select-object -Unique|sort    
    
    # Determine the number of columns: 
    $numberOfElements=$portsInUse.Count
    $columnWidth=.{$sortedArray=$portsInUse | sort;return ($sortedArray[$sortedArray.length-1]).tostring().Length+1}
    $numberOfColumns=[math]::Ceiling($numberOfElements/$columnWidth)
    #$columnHeight=[math]::ceiling($numberOfElements/$numberOfColumns)

    $portsInUse=$portsInUse|%{inflateString $_ $columnWidth}    
    $splitArray=splitArray $portsInUse $numberOfColumns
    $displayGrid=$splitArray|%{$_ -join ''} | out-string
    return $displayGrid
}

listPortsInUse
PS C:\Windows\system32> listPortsInUse
123   135   137   138   139   445
500   999   1900  3389  3702  4500
5040  5050  5353  5355  5357  7680
49196 49408 49664 49665 49666 49667
49668 49669 49670 49672 49684 49686
49788 50001 50002 50005 50131 50138
50199 50567 50917 50918 50924 50931
50951 51225 51341 51921 56807 58430
58431 58432 60458 64496

Leave a Reply

Your email address will not be published. Required fields are marked *