Skip to content

Instantly share code, notes, and snippets.

@PanosGreg
Created November 16, 2023 16:50
Show Gist options
  • Save PanosGreg/93b00463aa0c0cbb6c90c32611f23bd8 to your computer and use it in GitHub Desktop.
Save PanosGreg/93b00463aa0c0cbb6c90c32611f23bd8 to your computer and use it in GitHub Desktop.
From a string array get the uniques and retain the order
# from a string array get the uniques and retain the order
# get the unique items from a string array with case-insensitive and also retain the current order
# this approach is to work-around the gap from Select-Object -Unique, which compares the object and not the property
# in the case of string arrays.
# and also to retain the order, whereas the Sort-Object -Unique would change the order
# source string array
$StrArray = 'bb','BB','dd','DD','aa','AA','cc','CC'
# a) with Select-Object (as-is)
$StrArray | Select-Object -Unique
# it does not return the unique items, as-if it was case-sensitive
# b) with Select-Object (to lower case)
$StrArray.ToLower() | Select-Object -Unique
# it returns the unique ones and retains the order
# c) with Sort-Object
$StrArray | Sort-Object -Unique
# it returns the unique ones but changes the order
# d) with HashSet (not guaranteed)
$ICase = [System.StringComparer]::OrdinalIgnoreCase
[System.Collections.Generic.HashSet[string]]::new([string[]]$StrArray,$ICase)
# it returns the unique ones and retains the order, but NOT guaranteed
# The above approach is not 100% sure
# because hash sets are documented as unordered,
# i.e. the output order is not guaranteed to reflect the input order.
# e) with HashSet (guaranteed)
$ICase = [System.StringComparer]::OrdinalIgnoreCase
$HashSet = [System.Collections.Generic.HashSet[string]]::new($ICase)
$StrArray.Where({$Hashset.Add($_)})
# it returns the unique ones and retains the order, guaranteed
# the difference with the previous one is that this is slower and uses more memory
# but it is guaranteed that it will return the unique items and retain the order
# f) with LINQ (not guaranteed)
[System.Linq.Enumerable]::Where(
[System.Linq.Enumerable]::Distinct([string[]]$StrArray),
[Func[string, bool]] { $Args[0] -cmatch '^[a-z]+$' }
).ToArray()
# it returns the unique ones and retains the order, but NOT guaranteed
# g) with Where-Object function or .Where() method
$StrArray | where {$_ -cmatch '^[a-z]+$'}
$StrArray.Where({$_ -cmatch '^[a-z]+$'})
# it returns the unique ones and retains the order
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment