Converting hashtable to array of strings

David I. McIntosh's own answer works well, but it should be noted that the elements of the resulting array correspond to all lines of the default output, which includes:

  • the empty leading and trailing lines
  • the two header lines (the line with the column names and the separator line)

Out-String simply sends what you'd normally see in the console (terminal) to a string, by default as a single string, and with -Stream as an array of strings.

Here's a variation of David's command that removes both the header and the empty lines:

[string[]] $l_array = ($l_table | Out-String -Stream) -ne '' | select -Skip 2

The rest of this answer shows how to control the specifics of the string representation obtained; it uses PS v3+ syntax and built-in alias % for ForEach-Object for brevity.

Note: For clarity, the sample input hashtable is called $ht (not $l_table) in the following examples; the PSv4+ .ForEach() variants perform better.

  • Get all keys as a string array:

      $ht.Keys | % ToString # or (PSv4+): $ht.Keys.ForEach('ToString')
    
  • Get all values as a string array:

      $ht.Values | % ToString # or (PSv4+): $ht.Values.ForEach('ToString')
    
  • Get a custom representation of key-value pairs, in format <key>=<value>; note that .GetEnumerator() is needed to send the key-value pairs individually through the pipeline; by default, PowerShell passes a hashtable as a whole:

      $ht.GetEnumerator() | % { "$($_.Name)=$($_.Value)" }
    
      # or (PSv4+):
      $ht.GetEnumerator().ForEach({ "$($_.Name)=$($_.Value)" })
    

Note that while .ToString(), which is also applied implicitly during string interpolation (inside "...", an expandable string), works well with primitive .NET types (as well as additional numeric types such as [decimal] and [bigint]); generally, types will just print their full type name, unless their .ToString() method is explicitly overridden to return a more meaningful custom representation (which is what the primitive types do and which is the case with only some of the non-primitive types returned by PowerShell cmdlets).
Also note that using an array(-like data structure) inside an expandable string expands to the (stringified) elements concatenation of its elements with the value of the $OFS preference variable, which defaults to a space char. (e.g., $a='one', 'two'; "$a" expands to 'one two') - see this answer for more information on expandable strings (string interpolation) in PowerShell.

A simple example of choosing a property of a value to represent it in the string:

# Sample hashtable containing a value of a non-built-in type,
# [System.Diagnostics.Process]    
$ht = @{ one = 1; two = Get-Process -ID $PID }

# Use the `.Path` property to represent the value.
$ht.GetEnumerator()  | % { "$($_.Name)=$($_.Value.Path)" }

[string[]]$l_array = $l_table | out-string -stream

The hash is just a Hashtable so it has a keys and a values property.

$hash = @{}

$hash["foo"] = "bob"

$hash.Values

$hash.Values | Out-string

If you want to get the enumerator it will return you the keyvaluepair

$hash.GetEnumerator() |%{$_ | out-string}

Tags:

Powershell