Skip to content

Instantly share code, notes, and snippets.

@PanosGreg
Last active April 27, 2023 16:03
Show Gist options
  • Save PanosGreg/8fcfcff661f277cd1bab5eb8c63a6061 to your computer and use it in GitHub Desktop.
Save PanosGreg/8fcfcff661f277cd1bab5eb8c63a6061 to your computer and use it in GitHub Desktop.
3 different options to Sort
# 3 different options to Sort:
# 1) via an IComparer class,
# using the Sort() method from List and ArrayList
# or just instantiate a SortedSet
# 2) via LINQ
# using the OrderBy() method
# 3) via Sort() method from [Array]
## Custom IComparer for use with:
# - System.Collections.Generic.List
# - System.Collections.Generic.SortedSet
# - System.Collections.ArrayList
class ObjectComparer : Collections.Generic.IComparer[Management.Automation.PSObject] {
[string]$PropertyName
[bool]$Descending = $false
#region --- Constructors
ObjectComparer([string]$Property) {
$this.PropertyName = $Property
}
ObjectComparer([string]$Property, [bool]$Descending) {
$this.PropertyName = $Property
$this.Descending = $Descending
}
#endregion
#region --- Compare method
[int] Compare ([Management.Automation.PSObject]$a,
[Management.Automation.PSObject]$b) {
$ValueA = $a.$($this.PropertyName)
$ValueB = $b.$($this.PropertyName)
if ($ValueA -eq $ValueB) {$result = 0}
elseif ($ValueA -lt $ValueB) {$result = -1}
else {$result = 1}
if($this.Descending) {$result *= -1}
return $result
}
#endregion
}
# Create a list
$list = [System.Collections.Generic.List[pscustomobject]]::new()
# create some ps objects
$a = [pscustomobject] @{Name = 'aa' ; Size = 10}
$b = [pscustomobject] @{Name = 'bb' ; Size = 20}
$c = [pscustomobject] @{Name = 'cc' ; Size = 30}
# add them to the list in an unsorted order
$c,$a,$b | ForEach-Object {$list.Add($_)}
# have a look at the unsorted list
$list
# Instantiate a comparer based on the 'Name' property
$NameComparer = [ObjectComparer]::new('Name')
# Now sort the list
$list.Sort($NameComparer) # <-- it sorts in-place
# Have a look at the sorted list
$list
## you could also do the same with a SortedSet as well
$set = [System.Collections.Generic.SortedSet[pscustomobject]]::new($NameComparer)
$c,$a,$b | ForEach-Object {[void]$set.Add($_)}
$set
### NOTE: of course you can change the Comparer class to use different kinds of object types
# for ex. [IO.FileSystemInfo], [IO.DirectoryInfo], [Diagnostics.Process], [ServiceProcess.ServiceController], etc.
###### Alternatively you can sort with LINQ
$objects = $c,$a,$b
[Linq.Enumerable]::OrderBy([pscustomobject[]]$objects, [Func[pscustomobject,string]] {($args[0]).Name})
# LINQ is the only option that does NOT sort in-place, instead it outputs the results into a new object
### Or just use [array] (to sort based on the Name)
[array]::Sort($objects.Name,$objects)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment