Is there a better way to expand a calculated field?

I can do this but using Select-Object twice like this is ugly and probably inefficient. Is it possible to do an -ExpandProperty or equivalent on a calculated property?

Get-Wmiobject -Class Win32_LogicalDisk | Select @{n=‘Drive’;e={$_.DeviceID.TrimEnd(’:’)}} | Select -ExpandProperty Drive

You could just use ForEach-Object instead:

Get-Wmiobject -Class Win32_LogicalDisk | ForEach-Object { $_.DeviceID.TrimEnd(':') }

Not sure why you need the second select as

£> Get-Wmiobject -Class Win32_LogicalDisk |
Select @{n=’Drive’;e={$_.DeviceID.TrimEnd(‘:’)}}



If you just want the drive letters then go with Dave’s suggestion or make it shorter liek this
(Get-Wmiobject -Class Win32_LogicalDisk).DeviceID.TrimEnd(’:’)

@Richard - I am wanting an output as an array of strings and not an array of objects.

This is just academic tinkering mostly and figuring out how I can write this in the shortest way possible yet account for the instances when, for example, an array may contain 1,000,000+ items.

@Richard So far, I’ve tried your suggestion which was 20 seconds. I tried Dave’s suggestion and that was about the same. I also tried mine and it was about the same too. In this instance, it appears since they are the same performance-wise it’d be best to pick the shortest code which would be

(Get-Wmiobject -Class CIM_DataFile | Select -first 20000).DeviceID.TrimEnd(‘:’)

Am I right?

Depends on whether you intend to support PowerShell 2.0 or not. The (Get-Wmiobject -Class CIM_DataFile | Select -first 20000).DeviceID.TrimEnd(‘:’) syntax requires version 3.0 or later.

It will always be at least v3.

Thanks guys. I appreciate the help.

Is this any faster:

[string](gwmi win32_logicaldisk ) -split '\\\\.+?DeviceID="' -replace ':"'

Even if it is faster, it would be bad habit to go back to text parsing like that. PowerShell’s biggest strength is the ability to work with objects, not text.

For example, run it this way, and you’ll see that the text parsing approach looks correct at first, but actually outputs an extra empty string, and includes some unwanted whitespace:

[string](gwmi win32_logicaldisk ) -split '\\\\.+?DeviceID="' -replace ':"' |
ForEach-Object { "'$_'" }

I agree that doing text parsing is not something you want to do as a matter of course, but when a solution needs to scale to millions of operations I think purity can be put aside in favor of efficiency.

The better question is what are you trying to achieve with your script and what is the best way to reach that goal. I would always recommend outputting objects as the first option BUT there are times when it isn’t the right answer

In this instance I was not necessarily trying to achieve any real-world result. I appreciate the replies. I learned a few approaches that I had never considered before.

I’ve been experimenting with something similar. The purpose of -ExpandProperty is to convert an object to string, so that another cmdlet’s parameter can accept it, right? However, in a custom property you cannot use it, but you can use -as [string] - I mean if you only want to convert it, not trim or alike.

-ExpandProperty doesn’t necessarily convert to a string. It takes a property that can have one, or more, values and supplies you with the value(s). Those values could be of any type. In other words it strips the values out of the property