在哈希表数组上使用 Sort-Object
Using Sort-Object on array of hash tables
在 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 的调用 return 相同的 {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
,它 return 会按照输入的顺序排列对象,因此排序会改变顺序。但也许它没有比较器,所以只是将每个对象都视为平等的??
目标是对所有对象进行排序。我对涉及备用自定义对象、备用集合 and/or 备用排序例程的解决方法很好。
编辑:为了阐明我想要实现的目标,这将是 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);
Sort-Object a
不起作用,因为 a
不是 属性,它是散列 table 中的键。有人可能会感到困惑,因为 PowerShell 通过接受 $ht.a
为您隐藏了这一点,即使它实际上在幕后使用了 $ht["a"]
,但是如果您 运行 $array | Get-Member
您可以确认 属性 a
不存在。
解决方法是使用访问散列中键的计算属性进行排序table。我使用 Select-Object
在 table 中显示散列 table,因此更容易看到结果。例如:
$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
请参阅@Frode F. 的回答以获得详细解释,但该回答确实遗漏了一种情况。当外部容器只有一项时(即当数组只包含一个哈希表时),Sort-Object "conveniently" 对内部容器进行排序。
所以...
其中 $array.Count -eq 1
,该哈希表的元素已排序。
其中$array.Count -gt 1
,数组元素排序
作为解决方法,使用:
if ($array.Count -gt 1) {
$result = Sort-Object { $_.a }, {$_.b }
} else {
$result = $array
}
在 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 的调用 return 相同的 {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
,它 return 会按照输入的顺序排列对象,因此排序会改变顺序。但也许它没有比较器,所以只是将每个对象都视为平等的??
目标是对所有对象进行排序。我对涉及备用自定义对象、备用集合 and/or 备用排序例程的解决方法很好。
编辑:为了阐明我想要实现的目标,这将是 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);
Sort-Object a
不起作用,因为 a
不是 属性,它是散列 table 中的键。有人可能会感到困惑,因为 PowerShell 通过接受 $ht.a
为您隐藏了这一点,即使它实际上在幕后使用了 $ht["a"]
,但是如果您 运行 $array | Get-Member
您可以确认 属性 a
不存在。
解决方法是使用访问散列中键的计算属性进行排序table。我使用 Select-Object
在 table 中显示散列 table,因此更容易看到结果。例如:
$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
请参阅@Frode F. 的回答以获得详细解释,但该回答确实遗漏了一种情况。当外部容器只有一项时(即当数组只包含一个哈希表时),Sort-Object "conveniently" 对内部容器进行排序。
所以...
其中 $array.Count -eq 1
,该哈希表的元素已排序。
其中$array.Count -gt 1
,数组元素排序
作为解决方法,使用:
if ($array.Count -gt 1) {
$result = Sort-Object { $_.a }, {$_.b }
} else {
$result = $array
}