xlogI125’s blog

パソコン作業を効率化したい

PowerShell練習 配列のシャローコピーを並べ替えて返す

メモ

ソート後の値を返さないものよりも返すほうが、スクリプトの入力面で扱いやすい気がする。

使い捨てスクリプト

# PowerShell 5.1, Windows 11

Set-StrictMode -Version Latest

Add-Type -UsingNamespace System.Management.Automation `
-Namespace MyNS -Name MyCls -MemberDefinition @'

// String配列
public static string[] SortStr(string[] str) {
  // 受け取った配列をシャローコピー
  string[] ret = (string[])str.Clone();
  // 並べ替え
  Array.Sort(ret, (x, y) => StrCmpLogicalW(x, y));
  // 配列を返す
  return ret;
}

// PSObject配列
public static PSObject[] SortPSObj(PSObject[] obj, string propName = "Name") {
  // 受け取った配列をシャローコピー
  PSObject[] ret = (PSObject[])obj.Clone();
  // 並べ替え
  Array.Sort(ret, (x, y) => StrCmpLogicalW(
    x.Properties[propName].Value.ToString(), 
    y.Properties[propName].Value.ToString()
  ));
  // 配列を返す
  return ret;
}

// 文字列内の数字をテキストではなく数値と見なして比較
[DllImport(
  "Shlwapi.dll", CharSet = CharSet.Unicode, EntryPoint = "StrCmpLogicalW"
)]
private static extern int StrCmpLogicalW(
  [MarshalAs(UnmanagedType.LPWStr)] string psz1, 
  [MarshalAs(UnmanagedType.LPWStr)] string psz2
);

'@


# フォルダ名 [tmp]
$folderPath = "$($env:USERPROFILE)\Desktop\[tmp]"

$a1 = @(Get-ChildItem -LiteralPath $folderPath -File)
$a2 = @(Get-ChildItem -LiteralPath $folderPath -File)

$b = [MyNS.MyCls]::SortStr($a1.Name)
$c = [MyNS.MyCls]::SortPSObj($a2)

$a1 | Out-String -Width 80
$a2 | Out-String -Width 80

$a1 = $null
$a2 = $null

$b | Out-String -Width 80
$c | Out-String -Width 80

[MyNS.MyCls]::SortStr(@(9.870, 6.540, 3.210)) | Out-String -Width 80

[MyNS.MyCls]::SortStr(@(-9.87, -6.54, -3.21)) | Out-String -Width 80

[MyNS.MyCls]::SortStr(@("009.87", "06.54", "3.21")) | Out-String -Width 80

$d = @(
[PSCustomObject]@{ColA=9.870; ColB=-9.87; ColC="009.87"; Z="a3"}
[PSCustomObject]@{ColA=6.540; ColB=-6.54; ColC="06.54";  Z="a01"}
[PSCustomObject]@{ColA=3.210; ColB=-3.21; ColC="3.21";   Z="a005"}
)

[MyNS.MyCls]::SortPSObj($d, "ColA") | Out-String -Width 80

[MyNS.MyCls]::SortPSObj($d, "ColB") | Out-String -Width 80

[MyNS.MyCls]::SortPSObj($d, "ColC") | Out-String -Width 80

[MyNS.MyCls]::SortPSObj($d, "Z") | Out-String -Width 80