Skip to content

Instantly share code, notes, and snippets.

@AgainPsychoX
Last active August 23, 2023 08:31
Show Gist options
  • Save AgainPsychoX/4e6aabc8e8832a2afde1386d038eda31 to your computer and use it in GitHub Desktop.
Save AgainPsychoX/4e6aabc8e8832a2afde1386d038eda31 to your computer and use it in GitHub Desktop.
Sorting the same way Windows Explorer does
$array = @('1a2a5773', '0fe68296', '01b7f045')
$expected = @('0fe68296', '01b7f045', '1a2a5773')
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
Write-Host 'Bad:' # from https://stackoverflow.com/a/5429048/4880243
$array | Sort-Object { [regex]::Replace($_, '\d+', { $args[0].Value.PadLeft(20) }) }
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
Add-Type -TypeDefinition @"
using System.Runtime.InteropServices;
public static class NaturalSort
{
[DllImport("Shlwapi.dll", CharSet = CharSet.Unicode)]
private static extern int StrCmpLogicalW(string psz1, string psz2);
public static string[] Sort(string[] array)
{
System.Array.Sort(array, (psz1, psz2) => StrCmpLogicalW(psz1, psz2));
return array;
}
}
"@
Write-Host 'Good:' # from https://stackoverflow.com/a/65527560/4880243
[NaturalSort]::Sort($array)
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
function NaturalSort-Object {
[CmdletBinding(PositionalBinding=$false)]
param (
[Parameter(ValueFromPipeline)]
$InputObject,
[Parameter(Position=0)]
[string]$PropertyOrExpression,
[switch]$Descending
)
begin {
Add-Type -TypeDefinition @"
using System.Runtime.InteropServices;
using System.Collections;
public static class Shlwapi_StrCmpLogicalW
{
[DllImport("Shlwapi.dll", CharSet = CharSet.Unicode)]
private static extern int StrCmpLogicalW(string psz1, string psz2);
public class Comparer : IComparer
{
int IComparer.Compare(object x, object y)
{
return StrCmpLogicalW(x.ToString(), y.ToString());
}
}
public class ReversedComparer : IComparer
{
int IComparer.Compare(object x, object y)
{
return StrCmpLogicalW(y.ToString(), x.ToString());
}
}
public static TValue[] Sorted<TValue>(string[] keys, TValue[] items)
{
System.Array.Sort(keys, items, new Comparer());
return items;
}
public static TValue[] SortedDescending<TValue>(string[] keys, TValue[] items)
{
System.Array.Sort(keys, items, new ReversedComparer());
return items;
}
}
"@
$keys = @()
$items = @()
}
process {
if ($PropertyOrExpression -is [string]) {
$keys += ($InputObject | Select-Object -Property $Property)
}
elseif ($PropertyOrExpression -is [scriptblock]) {
$keys += ($InputObject | Select-Object $PropertyOrExpression)
}
else {
throw 'No property or expression provided'
}
$items += $_
}
end {
if ($Descending) {
return [Shlwapi_StrCmpLogicalW]::SortedDescending($keys, $items)
}
else {
return [Shlwapi_StrCmpLogicalW]::Sorted($keys, $items)
}
}
}
Write-Host 'Good (my take):'
$array | NaturalSort-Object
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Bad:
# 0fe68296
# 1a2a5773
# 01b7f045
# Good:
# 0fe68296
# 01b7f045
# 1a2a5773
# Good (my take):
# 0fe68296
# 01b7f045
# 1a2a5773
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment