Is there a better way to expand a calculated field?

This topic contains 13 replies, has 5 voices, and was last updated by  Richard Siddaway 3 years, 2 months ago.

  • Author
    Posts
  • #16012

    Adam Bertram
    Moderator

    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

  • #16013

    Dave Wyatt
    Moderator

    You could just use ForEach-Object instead:

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

    Richard Siddaway
    Moderator

    Not sure why you need the second select as

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

    Drive
    —–
    C
    D
    E
    F

    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(':')

  • #16016

    Adam Bertram
    Moderator

    @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?

    • #16025

      Rob Campbell
      Participant

      Is this any faster:


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

  • #16017

    Dave Wyatt
    Moderator

    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.

  • #16018

    Adam Bertram
    Moderator

    It will always be at least v3.

  • #16019

    Adam Bertram
    Moderator

    Thanks guys. I appreciate the help.

  • #16026

    Dave Wyatt
    Moderator

    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 { "'$_'" }
    
  • #16027

    Rob Campbell
    Participant

    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.

  • #16028

    Richard Siddaway
    Moderator

    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

  • #16029

    Adam Bertram
    Moderator

    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.

  • #16042

    Richard Siddaway
    Moderator

    -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

  • #16041

    Istvan Szarka
    Participant

    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.

You must be logged in to reply to this topic.