Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I stop Powershell filtering from converting my array to string?

Tags:

powershell

Observe this example:

PS C:\> $list=("A","B")
PS C:\> $list.GetType().Name
Object[]
PS C:\> ($list | ? {$_ -ne "C"}).GetType().Name
Object[]
PS C:\> ($list | ? {$_ -ne "B"}).GetType().Name
String

Why on earth is Powershell converting my array to a String when there's only one element left? It breaks further processing of the variable in my script where I assume the output is an Array. How can I prevent it?

like image 958
Nilzor Avatar asked Sep 06 '25 03:09

Nilzor


2 Answers

To explain why Powershell seemingly converts an array to a string is caused by the result of Where-Object / %'s filtering and data it returns.

When the first version filters elements not equal to "C", the result is a collection. There were more than one matching member: "A" and "B". Thus, a collection is needed to contain both values.

The second version returns just a single object, "A", and thus it's a string instead of a collection. Since there is just a single object, there is no need to return an array with one element - just the object itself.

Theo's answer works by making Where-Object's output to be an array. The array sub-expression operator @() can be used to create arrays. Like so,

# Convert where-object's output into an array,
# even if there is only a single object.
@($list | ? {$_ -ne "B"}) 
like image 132
vonPryz Avatar answered Sep 10 '25 02:09

vonPryz


To complement my comment and vonPryz's answer

PowerShell 'unravels' one-element arrays when returning from a function or scriptblock into a single scalar, in this case a string.

To prevent that from interfering with the rest of the code which expects an array, no matter if it is empty or has only one element, you can force the output to become an array by wrapping it inside @().

In your case,

($list | ? {$_ -ne "B"})

would return the single element A, turned into a scalar String, while

@($list | ? {$_ -ne "B"}).GetType().Name

returns an array (Object[]) with just one element in it.

like image 23
Theo Avatar answered Sep 10 '25 02:09

Theo