4

I create an array of objects that hold the lengths of files with this command:

$lengths = dir -File | Sort-Object -Descending | Select-Object Length -First 5

However, I want this to be an array of integers, not objects, so I can edit the values easily. How can I convert this $lengths object array into an integer array?

Thank You! :)

3
  • 1
    Expand the Property, Select-Object -Expand Length. then you can hard type the var if needed, [int64[]] $lengths = ... Commented Sep 24, 2022 at 18:08
  • Most frequently asked question evar. Also | foreach-object propertyname. Commented Sep 24, 2022 at 21:28
  • how can you not change an object's property? Everything in PowerShell is an object, even an integer or a float Commented Sep 25, 2022 at 2:48

2 Answers 2

4

The answer was provided in comments but to give it closure, you can expand the values of the objects using Select-Object -ExpandProperty. It's worth noting that your Sort-Object statement is not actually sorting by Length unless you specify the property to be sorted:

$length = dir -File | Sort-Object Length -Descending | Select-Object -ExpandProperty Length -First 5

Personal preference to expand the values, you can use ForEach-Object, the syntax is far easier in my opinion but there is no -First X here:

$length = dir -File | ForEach-Object Length | Sort-Object -Descending

$length type will be object[] (object array) even though it will contain an array of int64 values, this is default type for arrays in PowerShell, you can however provide a desired output type either by type casting or hard typing. Looking into the Cast Operator [..] is a good starting point.

# type casting
$length = [Int64[]] (dir -File | ....)

# hard typing
[Int64[]] $length = dir -File | ....

For the latter, $length is constrained to be assigned int64 values or values that can be type coerced to int64, i.e.:

[int64[]] $length = 0..10

# can be assigned an `int32` and the array element will be converted to `int64`
$length = 1
$length[0].GetType() # => `int64`

# can be assigned a `string` which contains for example a decimal value
$length = '1.1', 2
# gets converted to int64 (no longer a decimal value)
$length[0] # => 1

# cannot be assigned a `string` which does not contain a type of numeric value
$length = 1, 'hello' # => ...Cannot convert value "hello" to type "System.Int64"...

While the former only enforces the type of the array elements however a new array of different type can be assigned:

$length    = [int64[]] (0..10)
$length[0] = 'hello' # => ...Cannot convert value "hello" to type "System.Int64"...

$length = 'new', 'object', 'array' # succeeds
Sign up to request clarification or add additional context in comments.

1 Comment

Nice. Small correction: When no properties are specified, Sort-Object tries to use default sort property (in this case Name) and if there is no default sort property it compares property by property. learn.microsoft.com/en-us/powershell/module/…
1

Unfortunately, you can't use Memeber Access Enumeration for Length because it's also a property of the collection (Unlike, for example, (gci -af).LastwriteTime). But another way to obtain your desired array is:

$Length = (gci -af).Foreach({$_.Length}) | sort -Descending

Without casting, $Length is the generic object array:

PS > $Length.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]

But all its elements are the same type:

PS > ($Length | gm).TypeName | select -Unique
System.Int64

1 Comment

Nice call adding on why member access enumeration is not possible in this case

Your Answer

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