Hello,
How do I format into a table such a structure where columns in table will be Hashtable’s indexes
Code
$array = @();
$hashtable = @{Col1="1"; Col2="2"};
$array += $hashtable;
$array += $hashtable;
$array | ft
Output
Name Value
---- -----
Col2 2
Col1 1
Col2 2
Col1 1
Desired Output
Col1 Col2
1 2
1 2
system
March 14, 2015, 12:10am
2
You need to turn your hashtables into objects with Col1 and Col2 as properties. As it turns out, that’s incredibly easy:
# PowerShell 3.0 and later:
$array | ForEach-Object { [pscustomobject] $_ } | Format-Table
# PowerShell 2.0-compatible:
$array | ForEach-Object { New-Object -TypeName psobject -Property $_ } | Format-Table
This did not work. I’m V4
$array = @();
$hashtable = @{Col1="1"; Col2="2"};
$array += $hashtable;
$array += $hashtable;
$array | ForEach-Object { [pscustomobject] $_ } | Format-Table
output
Name Value
---- -----
Col2 2
Col1 1
Col2 2
Col1 1
system
March 14, 2015, 12:47am
4
Don’t know what to tell you. I ran the code before I posted, and it works fine for me.
How is this possible? This works for you?
system
March 14, 2015, 4:12am
6
I’m not seeing an image in your last post, but here’s what works for me. I’m running the latest preview of PowerShell 5.0, but as far as I know, nothing’s changed with the way this works since v3. (I don’t have any older systems online at the moment to test, though).
system
March 14, 2015, 4:18am
8
Well, do it the other way, then.
Yes, v2 way works but I do have v4 though
PS C:\WINDOWS\system32> $PSVersionTable
Name Value
PSVersion 4.0
WSManStackVersion 3.0
SerializationVersion 1.1.0.1
CLRVersion 4.0.30319.34014
BuildVersion 6.3.9600.17090
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0}
PSRemotingProtocolVersion 2.2
I’m seeing the same thing, so it’s not just your PowerShell misbehaving.
PS C:\Users\Martin> $array = @();
$hashtable = @{Col1="1"; Col2="2"};
$array += $hashtable;
$array += $hashtable;
$array | ForEach-Object { [pscustomobject] $_ } | Format-Table
Name Value
---- -----
Col2 2
Col1 1
Col2 2
Col1 1
PS C:\Users\Martin> $array = @();
$hashtable = @{Col1="1"; Col2="2"};
$array += $hashtable;
$array += $hashtable;
$array | ForEach-Object { New-Object psobject -Property $_ } | Format-Table
Col2 Col1
---- ----
2 1
2 1
PS C:\Users\Martin> $Host
Name : Windows PowerShell ISE Host
Version : 4.0
InstanceId : 95a1a0f8-a342-44e6-a47e-5a2cdc5ae206
UI : System.Management.Automation.Internal.Host.InternalHostUserInterface
CurrentCulture : en-US
CurrentUICulture : en-US
PrivateData : Microsoft.PowerShell.Host.ISE.ISEOptions
IsRunspacePushed : False
Runspace : System.Management.Automation.Runspaces.LocalRunspace
But with that said, I never liked the typecasting approach, and New-Object is faster anyway.
Fiddling around with it, I see that I can typecast the $hashtable variable, but I can’t typecast the pipeline object taken from an array of hashtables. Interesting.
PS C:\Users\Martin> [pscustomobject]$array[0]
Col2 Col1
---- ----
2 1
PS C:\Users\Martin> $array | foreach { [pscustomobject]$_ }
Name Value
---- -----
Col2 2
Col1 1
Col2 2
Col1 1
PS C:\Users\Martin> $array | foreach { $_.GetType() }
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Hashtable System.Object
True True Hashtable System.Object
PS C:\Users\Martin> $array[0].GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Hashtable System.Object
Actually typecasting is faster. Damn.
It appears to be a bug when piping into the ForEach-Object cmdlet. I can’t seem to reproduce it using any other looping method.
PS C:\Users\Martin> foreach($item in $array) { [pscustomobject]$item }
Col2 Col1
---- ----
2 1
2 1
PS C:\Users\Martin> $array.ForEach({ [pscustomobject]$_ })
Col2 Col1
---- ----
2 1
2 1
Even passing a single item into ForEach-Object fails
PS C:\Users\Martin> $array[0] | ForEach-Object { [pscustomobject]$_ }
Name Value
---- -----
Col2 2
Col1 1