在散列表数组上使用Sort-Object

时间:2016-05-04 17:13:10

标签: sorting powershell powershell-v2.0

在PowerShell(版本2)中创建以下哈希表数组后:

$array = @()
$array += @{a = 1; b = 5}
$array += @{a = 3; b = 4}
$array += @{a = 5; b = 9}
$array += @{a = 7; b = 2}

对Sort-Object的所有以下调用都返回相同的{a,b}序列:{5,9},{7,2},{1,5},{3,4}:

$array | Sort-Object
$array | Sort-Object -Descending
$array | Sort-Object a
$array | Sort-Object b
$array | Sort-Object "a"
$array | Sort-Object -Property a
$array.GetEnumerator() | Sort-Object
$array.GetEnumerator() | Sort-Object a

如果直接调用$array,它将按照输入的顺序返回对象,因此排序正在改变顺序。但也许它没有比较器所以只是将每个对象都视为相等?

目标是对所有对象进行排序。我很好处理涉及备用自定义对象,备用集合和/或备用排序例程的变通方法。

编辑:为了澄清我想要实现的目标,这在C#中是一个粗略的等价物

class MyClass {
    public int a;
    public int b;
}

// somewhere inside a method:
var objects = new List<MyClass>();
// code here to populate objects with some MyClass instances.
var sorted = objects.OrderBy(x => x.a);

2 个答案:

答案 0 :(得分:5)

Sort-Object a无效,因为a不属于某个属性,它是哈希表中的键。有人可能会感到困惑,因为PowerShell通过接受$ht.a为您隐藏了这一点,即使它实际上在幕后使用$ht["a"],但如果您运行$array | Get-Member,则可以确认属性a不存在。

解决方法是使用访问哈希表中的键的计算属性进行排序。我使用Select-Object在表格中显示哈希表,以便更容易看到结果。例如:

$array = @()
$array += @{a = 7; b = 2}
$array += @{a = 3; b = 4}
$array += @{a = 3; b = 1}
$array += @{a = 5; b = 9}
$array += @{a = 1; b = 5}

#No sort
$array | Select-Object @{n="a";e={$_.a}}, @{n="b";e={$_.b}}

a b
- -
7 2
3 4
3 1
5 9
1 5

#Sort by a asc, then b asc
$array | Sort-Object { $_.a },  { $_.b } | Select-Object @{n="a";e={$_.a}}, @{n="b";e={$_.b}}

a b
- -
1 5
3 1
3 4
5 9
7 2

答案 1 :(得分:1)

请参阅@Frode F.的答案以获得详细解释,但答案确实错过了一种情况。当外部容器只有一个项目时(即当数组只包含一个哈希表时),Sort-Object“方便地”对内部容器进行排序。

所以... 在$array.Count -eq 1的位置,该哈希表的元素被排序。 在$array.Count -gt 1的位置,数组的元素被排序。

作为解决方法,请使用:

if ($array.Count -gt 1) {
    $result = Sort-Object { $_.a }, {$_.b }
} else {
    $result = $array
}