0

I am storing data in a hashtable with multiple values like this:

$hash = @{}
$folders = dir (...) | where (...)
foreach ($folder in $folders) {
    $num1 = (...)
    $num2 = (...)
    $hash.Add($folder.Name,@($num1,$num2))
}

So this is a hash with an array in its value part. The array always got two items. When finished the foreach part I want to show the data with Out-GridView like this:

$hash | select -Property @{Expression={$_.Name};Label="FolderName"},
    @{Expression={$_.Name[0]};Label="num1"},
    @{Expression={$_.Name[1]};Label="num2"} | Out-GridView

But as you can imagine, this is not working. How can I split the stored array in the value part of my hash into two new columns to show them in overall three columns in the GridView?

Should be something like Name, Value1, Value2 ...

And then multiple items which are stored in the hashtable as multiple rows.

1 Answer 1

2

Hashtables are not lists of objects with a Name and a Value property. That's just how PowerShell displays the data structure for your convenience. For processing a hashtable the way you tried you need an enumerator to produce such objects:

$hash.GetEnumerator() |
    Select-Object @{n='FolderName';e={$_.Name}},
                  @{n='num1';e={$_.Value[0]}},
                  @{n='num2';e={$_.Value[1]}} |
    Out-GridView

Or you can enumerate the keys of the hashtable, use them as the current objects in the pipeline, and look up the values by the respective key and index:

$hash.Keys |
    Select-Object @{n='FolderName';e={$_}},
                  @{n='num1';e={$hash[$_][0]}},
                  @{n='num2';e={$hash[$_][1]}} |
    Out-GridView

If you don't know the number of array elements beforehand you need an inner loop for processing the nested arrays, e.g. like this:

$hash.Keys | ForEach-Object {
  $o = New-Object -Type PSObject -Property @{ 'FolderName' = $_ }
  $a = $hash[$_]
  for ($i = 1; $i -le $a.Count; $i++) {
    $o | Add-Member -Type NoteProperty -Name "num$i" -Value $a[$i-1]
  }
  $o
} | Out-GridView

If you have a variable number of array elements, beware that PowerShell determines by the first object which properties will be displayed.

Sign up to request clarification or add additional context in comments.

6 Comments

This solution works fine but provides no information about why the solution of Hamstibamsti didn't work. You should elaborate why there is no property named "Name" and that he can check the properties of $hash using the get-member cmdlet.
Thanks for your help. Tom is right, in your second approach, where you were enumerating the keys of the hashtable, you use $hash[$_][0]. Why is this not working in my approach? It is even not working, when I am trying: $hash.Keys | select $hash[$_][0]. Why does your approach work nonetheless? Where is the difference? To my mind, it is the same piece of code?
@Hamstibamsti $_.Name[0] != $hash[$_][0]. $_.Name[0] couldn't possibly work even if you were enumerating anything (which you're not), since the name (key) isn't an array in the first place. Also, $hash[$_][0] isn't the name of a property of the keys, so you must use a calculated property if you want to use it with Select-Object.
Thanks again, so the transformation of the data via @{Expression=(...) in Select-Object is responsible for making it work?
"A calculated property a property of an object, but not an inherent, built-in property. Instead, it’s a property we create ourselves." Thanks!
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.