xlogI125’s blog

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

GroupInfoの配列をNameプロパティで並べ替え

  • Group-Object の出力である GroupInfo の配列を Name プロパティで並べ替え
    • 並べ替え: System.Array.Sort
    • 比較: StrCmpLogicalW

使い捨てスクリプト

テスト環境: PowerShell 5.1, Windows 11 (2023年1月頃)

using namespace Microsoft.PowerShell.Commands

Set-StrictMode -Version Latest

Add-Type `
-Language CSharp `
-ReferencedAssemblies Microsoft.PowerShell.Commands.Utility `
-TypeDefinition @'
namespace MyNS {
  using Microsoft.PowerShell.Commands;
  using System.Collections.Generic;
  using System.Runtime.InteropServices;

  // 自然順
  public class CmpGrNameStrCmpLW : Comparer<GroupInfo> {
    public override int Compare(GroupInfo x, GroupInfo y) {
      return StrCmpLogicalW(x.Name, y.Name);
    }

    [DllImport("Shlwapi.dll", CharSet = CharSet.Unicode)]
    private static extern int StrCmpLogicalW(
      [MarshalAs(UnmanagedType.LPWStr)] string psz1, 
      [MarshalAs(UnmanagedType.LPWStr)] string psz2
    );
  }

  // ユーザー設定順
  public class CmpGrNameArrStr : Comparer<GroupInfo> {
    public string[] arr;

    public CmpGrNameArrStr(string[] arr) {
      this.arr = arr;
    }

    public override int Compare(GroupInfo x, GroupInfo y) {
      int iox = System.Array.IndexOf(this.arr, x.Name);
      int ioy = System.Array.IndexOf(this.arr, y.Name);

      if (iox > ioy) { return 1; }
      else if (iox < ioy) { return -1; }

      return 0;
    }
  }
}
'@

$psObj = @(Import-CSV -LiteralPath $args[0] -Encoding UTF8)

# 並べ替え前の順位を追加
for ($i = 0; $i -lt $psObj.Length; $i++) {
  $psObj[$i] | Add-Member -NotePropertyMembers @{Before = ($i + 1)}
}

function Sort-GrObjName {
  param(
    [ValidateNotNullOrEmpty()][PSObject[]]$pso, 
    [ValidateNotNullOrEmpty()][string[]]$prop, 
    [ValidateNotNullOrEmpty()][object[]]$comparer
  )

  # Group-Object
  $gi = [GroupInfo[]]@($pso | Group-Object -Property $prop[0])

  # System.Array.Sort
  [Array]::Sort($gi, $comparer[0])

  if ($prop.Length -eq 1) {
    $gi.Group
    return
  }

  for ($k = 0; $k -lt $gi.Length; $k++) {
    Sort-GrObjName `
      $gi[$k].Group `
      $prop[1..$prop.GetUpperBound(0)] `
      $comparer[1..$comparer.GetUpperBound(0)]
  }

  return
}

$property = @(
  "col1"
  "col2"
  "col3"
  "col4"
)

$comparerGroupInfo = @(
  [MyNS.CmpGrNameStrCmpLW]::new()
  [MyNS.CmpGrNameStrCmpLW]::new()
  [MyNS.CmpGrNameStrCmpLW]::new()
  [MyNS.CmpGrNameArrStr]::new(@("優", "良", "可", "不可"))
)

$psObj = Sort-GrObjName $psObj $property $comparerGroupInfo

# 並べ替え後の順位を追加
for ($i = 0; $i -lt $psObj.Length; $i++) {
  $psObj[$i] | Add-Member -NotePropertyMembers @{After = ($i + 1)}
}

$psObj | Format-Table

$csv = $psObj | ConvertTo-Csv -NoTypeInformation

$csv | Set-Clipboard
  • ps1ファイル
  • ショートカット(.lnk)
    • リンク先(T): PowerShell.exe -NoLogo -NoExit -NoProfile -ExecutionPolicy RemoteSigned -File "%USERPROFILE%\Desktop\Sort-GrObjName.ps1"
    • 作業フォルダー(S): ""

並べ替え例

並べ替え前

col1 col2 col3 col4
W030 H030 D2
W030 H030 D20
W030 H030 D6
W030 H08 D2
W030 H08 D20
W030 H08 D6
W030 H5 D2
W030 H5 D20
W030 H5 D6
W05 H030 D2
W05 H030 D20
W05 H030 D6
W05 H08 D2
W05 H08 D20
W05 H08 D6
W05 H5 D2
W05 H5 D20
W05 H5 D6
W3 H030 D2
W3 H030 D20
W3 H030 D6
W3 H08 D2
W3 H08 D20
W3 H08 D6
W3 H5 D2
W3 H5 D2 不可
W3 H5 D2
W3 H5 D2
W3 H5 D20
W3 H5 D6
W99 H99 D0100
W99 H99 D0100
W99 H99 D100
W99 H99 D100
W99 H99 D99
W99 H99 D99 不可
W99 H99 D99 不可
W99 H99 D99
W99 H99 D99

並べ替え後の例

col1 col2 col3 col4 Before After
W3 H5 D2 27 1
W3 H5 D2 28 2
W3 H5 D2 25 3
W3 H5 D2 不可 26 4
W3 H5 D6 30 5
W3 H5 D20 29 6
W3 H08 D2 22 7
W3 H08 D6 24 8
W3 H08 D20 23 9
W3 H030 D2 19 10
W3 H030 D6 21 11
W3 H030 D20 20 12
W05 H5 D2 16 13
W05 H5 D6 18 14
W05 H5 D20 17 15
W05 H08 D2 13 16
W05 H08 D6 15 17
W05 H08 D20 14 18
W05 H030 D2 10 19
W05 H030 D6 12 20
W05 H030 D20 11 21
W030 H5 D2 7 22
W030 H5 D6 9 23
W030 H5 D20 8 24
W030 H08 D2 4 25
W030 H08 D6 6 26
W030 H08 D20 5 27
W030 H030 D2 1 28
W030 H030 D6 3 29
W030 H030 D20 2 30
W99 H99 D99 38 31
W99 H99 D99 39 32
W99 H99 D99 35 33
W99 H99 D99 不可 36 34
W99 H99 D99 不可 37 35
W99 H99 D0100 32 36
W99 H99 D0100 31 37
W99 H99 D100 33 38
W99 H99 D100 34 39