Public/Invoke-PSMelt.ps1
function Invoke-PSMelt { <# .SYNOPSIS Unpivot a given array from wide format to long format #> param( [string[]]$Id, [string[]]$Vars, [string[]]$ExcludeProperty, $VarName = "variable", $ValueName = "value", [Parameter(ValueFromPipeline)] $InputObject ) process { if ($null -eq $InputObject) { return $null } #By NOT gathering the objects and processing in an end block, we can melt rows with disimilar columns; but skip figuring columnnames when all piped items are the same $propertyNames = $InputObject[0].psobject.Properties.name $newprops = $propertyNames -join '' if ($oldprops -ne $newProps) { #Allow exclude property to be an array of wildcards. Regex would match "name" to "parentname" foreach ($e in $ExcludeProperty) {$propertyNames = $propertyNames.where({$_ -notlike $e}) } if (!$Vars) { $Vars = $propertyNames foreach ($i in $Id) {$Vars = $Vars.where({$_ -notlike $i }) } } $oldProps = $newprops } #if we loop by columns (vars then records), we need to re-create the hash table every time. by rows (records the vars) we only create a new one once per row foreach ($record in $InputObject) { $h = [ordered]@{} foreach ($idItem in $Id) {$h[$idItem] = $record.$idItem} foreach ($var in $Vars) { $h[$VarName] = $var $h[$ValueName] = $record.$var [pscustomobject]$h } } } } |