这是可以理解的混淆,但正如您所说,哈希表键不是对象属性。
对它们一视同仁可能很诱人(有时这样有效),但这种情况绝对不会。
部分原因是您使用的是不同的 cmdlet,而不是直接的语言语义。
哈希表可以对它们的键使用点表示法,但键是不是属性,当您使用Group-Object 的-Property 参数时,您正在寻找专门的属性,而不仅仅是“任何东西”你可以用一个点访问”。
如您所见,采用脚本块的该参数的另一种形式是将执行的代码,因此块返回的任何值都会被分组。
更直接地回答您的问题:
第二个组对象实际上在做什么?
它正在当前对象(即哈希表)上(特别是)寻找 属性。
如果您想查看其中一个对象的属性是什么样的,请尝试以下操作:
$list.Values[0].PSObject.Properties | ft
它认为'order'属性是什么?
它不认为它是什么;它查找具有该名称的属性,如果找到,则使用该值;否则它使用$null。
你会得到相同的结果:
$list.Values | group -Property FakeProp
或
$list.Values | group -Property { $null }
在评论中解决您的问题:
有什么方法可以知道“什么时候应该”和“什么时候不应该”,
我应该只是推迟使用脚本块,什么时候使用-Property
优先于 { ... }?
-Property(不带脚本块)是首选,只要您要分组的值可用作被检查对象的直接属性。如果它是某个属性的属性、某个计算值、哈希表键/值或其他任何内容,请使用脚本块。我将这些称为“复杂值”。
如果复杂值有用,您可能希望将其添加为对象本身的实际属性来封装它;那么你可以直接引用它。此示例并不真正适合您的哈希表情况,但请考虑代表人的对象。它们有 2 个属性:Name 和 DateOfBirth。
$people 是这些对象的数组,您想按年龄对人进行分组(请忽略我不准确的年龄确定代码)。
$people | Group-Object -Property { ([DateTime]::Now - $_.DateOfBirth).Days / 365 -as [int] }
如果您再也不需要知道年龄也没关系;当然这不太可能,而且这看起来有点乱。应该更直接地明确您要“按年龄分组”。
相反,您可以使用Add-Member 将自己的(计算的)Age 属性添加到现有对象:
$people |
Add-Member -MemberType ScriptProperty -Name Age -Value {
([DateTime]::Now - $this.DateOfBirth).Days / 365 -as [int]
} -Force
从现在开始,$people 数组中的每个对象都有一个 Age 属性,该属性是根据 DateOfBirth 属性的值计算得出的。
现在你可以让你的代码更清晰了:
$people | Group-Object -Property Age
同样,这并不能真正解决您的哈希表问题;事实是它们在分组方面效果不佳。如果您要对它们进行大量分组,并且您真的不需要哈希表,请将它们变成对象:
$objs = $list.Values |
ForEach-Object -Process {
New-Object -TypeName PSObject -Property $_ # takes a hashtable
}
或
$objs = $list.Values |
ForEach-Object -Process {
[PSCustomObject]$_ # converts a hashtable to PSObject
}
然后:
$objs | Group-Object -Property Order