如何使用整数键访问有序 PowerShell 哈希 table 中的值?
How do I access values in an ordered PowerShell hash table using integer keys?
我的要求是使用 ordered 哈希 table.
中的整数键存储整数键并访问哈希 table 值
有效方法
当我使用字符串键时,没问题:
cls
$foo=[ordered]@{}
$foo.add("12",1)
$foo.add("24",2)
write-host ("first item=" + $foo.Item("12"))
write-host ("second item=" + $foo.Item("24"))
输出:
first item=1
second item=2
使用括号失败
当我使用括号时,程序没有抛出异常,但是returns什么都没有:
$fooInt=[ordered]@{}
$fooInt.add(12,1)
$fooInt.add(24,2)
write-host ("first item=" + $fooInt[12])
write-host ("second item=" + $fooInt[24])
输出:
first item=
second item=
使用 Item 方法失败
当我使用 Item 方法和整数键时,PowerShell 将整数键解释为索引而不是键:
$fooInt=[ordered]@{}
$fooInt.add(12,1)
$fooInt.add(24,2)
write-host ("first item=" + $fooInt.Item(12))
write-host ("second item=" + $fooInt.Item(24))
输出:
Exception getting "Item": "Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index"
At line:8 char:1
+ write-host ("first item=" + $fooInt.Item(12))
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], GetValueInvocationException
+ FullyQualifiedErrorId : ExceptionWhenGetting
Exception getting "Item": "Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index"
At line:9 char:1
+ write-host ("second item=" + $fooInt.Item(24))
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], GetValueInvocationException
+ FullyQualifiedErrorId : ExceptionWhenGetting
如何使用整数键访问 PowerShell 哈希table中的值?
哈希表中的键是对象,而不是字符串。当您尝试使用整数 12
访问密钥 "12"
时,它找不到该条目,因为密钥不匹配。
但是,您没有使用标准哈希表,您使用的是 ordered 哈希表,它具有不同的 Item
方法,因为它可以通过键或索引。如果你想访问有序哈希表的整数键,你需要使用不同的语法:
$hash.12
如果使用数组访问器语法:
$hash[12]
它将尝试 return 列表中的第 13 个项目。
您可以使用Get-Member
:
观察这些对象之间的区别
$orderedHash | Get-Member Item
TypeName: System.Collections.Specialized.OrderedDictionary
Name MemberType Definition
---- ---------- ----------
Item ParameterizedProperty System.Object Item(int index) {get;set;}, System.Object Item(System.Object key) {get;set;}
$hash | Get-Member Item
TypeName: System.Collections.Hashtable
Name MemberType Definition
---- ---------- ----------
Item ParameterizedProperty System.Object Item(System.Object key) {get;set;}
经过更多的实验,这只是 int32
类型的情况。如果您使用不同的类型定义和访问它,它将起作用,因为它不再匹配重载的 int
签名:
$hash = [ordered]@{
([uint32]12) = 24
}
$hash[[uint32]12]
> 24
总结
$fooInt.Item([object]12)
或 $fooInt[[object]12]
推理
如 TheIncorrigible1 的回答所示,.Item
有过载;它由 get_Item
:
方法支持
PS C:\> $fooInt.get_Item
OverloadDefinitions
-------------------
System.Object get_Item(int index)
System.Object get_Item(System.Object key)
System.Object IOrderedDictionary.get_Item(int index)
System.Object IDictionary.get_Item(System.Object key)
采用整数并进行索引的版本来自 IOrderedDictionary
接口,正常的 IDictionary 键查找采用 [System.Object]
。当您尝试将它与整数参数一起使用时,PowerShell 会绑定采用 [int]
的版本,因为它更匹配,并运行那个版本。
早些时候,我评论了如何使用反射来挑选出您想要的重载并调用它,但它很丑陋:
$fooInt.GetType().GetMethods().where{
$_.Name -eq 'get_Item' -and $_.GetParameters().Name -eq 'Key'
}.Invoke($fooInt, 'Public', $null, 12, $null)
^ your parameter
仔细想想,[int]
是一个值类型,而不是引用类型,这意味着.Net 必须将它装箱到一个对象中以将其放入哈希表中。因此,如果您在查找时也将整数参数放入一个对象中,PowerShell 可能会绑定到您想要的重载并进行键查找并仍然匹配正确的键..你知道什么,它有效:
PS C:\> $fooInt=[ordered]@{}
PS C:\> $fooInt.add(12,1)
PS C:\> $fooInt.add(24,2)
PS C:\> write-host ("first item=" + $fooInt.Item([object]12))
first item=1
它也适用于索引:
PS C:\> write-host ("first item=" + $fooInt[[object]12])
first item=1
这与 TheIncorrigible1 的实验非常接近,除了您不需要定义字典并将其键入为其他内容,然后将查找转换为匹配类型,您只需要通过转换为对象来访问它,因为您定义的键已经在内部发生了。
我的要求是使用 ordered 哈希 table.
中的整数键存储整数键并访问哈希 table 值有效方法
当我使用字符串键时,没问题:
cls
$foo=[ordered]@{}
$foo.add("12",1)
$foo.add("24",2)
write-host ("first item=" + $foo.Item("12"))
write-host ("second item=" + $foo.Item("24"))
输出:
first item=1
second item=2
使用括号失败
当我使用括号时,程序没有抛出异常,但是returns什么都没有:
$fooInt=[ordered]@{}
$fooInt.add(12,1)
$fooInt.add(24,2)
write-host ("first item=" + $fooInt[12])
write-host ("second item=" + $fooInt[24])
输出:
first item=
second item=
使用 Item 方法失败
当我使用 Item 方法和整数键时,PowerShell 将整数键解释为索引而不是键:
$fooInt=[ordered]@{}
$fooInt.add(12,1)
$fooInt.add(24,2)
write-host ("first item=" + $fooInt.Item(12))
write-host ("second item=" + $fooInt.Item(24))
输出:
Exception getting "Item": "Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index"
At line:8 char:1
+ write-host ("first item=" + $fooInt.Item(12))
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], GetValueInvocationException
+ FullyQualifiedErrorId : ExceptionWhenGetting
Exception getting "Item": "Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index"
At line:9 char:1
+ write-host ("second item=" + $fooInt.Item(24))
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], GetValueInvocationException
+ FullyQualifiedErrorId : ExceptionWhenGetting
如何使用整数键访问 PowerShell 哈希table中的值?
哈希表中的键是对象,而不是字符串。当您尝试使用整数 12
访问密钥 "12"
时,它找不到该条目,因为密钥不匹配。
但是,您没有使用标准哈希表,您使用的是 ordered 哈希表,它具有不同的 Item
方法,因为它可以通过键或索引。如果你想访问有序哈希表的整数键,你需要使用不同的语法:
$hash.12
如果使用数组访问器语法:
$hash[12]
它将尝试 return 列表中的第 13 个项目。
您可以使用Get-Member
:
$orderedHash | Get-Member Item
TypeName: System.Collections.Specialized.OrderedDictionary
Name MemberType Definition
---- ---------- ----------
Item ParameterizedProperty System.Object Item(int index) {get;set;}, System.Object Item(System.Object key) {get;set;}
$hash | Get-Member Item
TypeName: System.Collections.Hashtable
Name MemberType Definition
---- ---------- ----------
Item ParameterizedProperty System.Object Item(System.Object key) {get;set;}
经过更多的实验,这只是 int32
类型的情况。如果您使用不同的类型定义和访问它,它将起作用,因为它不再匹配重载的 int
签名:
$hash = [ordered]@{
([uint32]12) = 24
}
$hash[[uint32]12]
> 24
总结
$fooInt.Item([object]12)
或 $fooInt[[object]12]
推理
如 TheIncorrigible1 的回答所示,.Item
有过载;它由 get_Item
:
PS C:\> $fooInt.get_Item
OverloadDefinitions
-------------------
System.Object get_Item(int index)
System.Object get_Item(System.Object key)
System.Object IOrderedDictionary.get_Item(int index)
System.Object IDictionary.get_Item(System.Object key)
采用整数并进行索引的版本来自 IOrderedDictionary
接口,正常的 IDictionary 键查找采用 [System.Object]
。当您尝试将它与整数参数一起使用时,PowerShell 会绑定采用 [int]
的版本,因为它更匹配,并运行那个版本。
早些时候,我评论了如何使用反射来挑选出您想要的重载并调用它,但它很丑陋:
$fooInt.GetType().GetMethods().where{
$_.Name -eq 'get_Item' -and $_.GetParameters().Name -eq 'Key'
}.Invoke($fooInt, 'Public', $null, 12, $null)
^ your parameter
仔细想想,[int]
是一个值类型,而不是引用类型,这意味着.Net 必须将它装箱到一个对象中以将其放入哈希表中。因此,如果您在查找时也将整数参数放入一个对象中,PowerShell 可能会绑定到您想要的重载并进行键查找并仍然匹配正确的键..你知道什么,它有效:
PS C:\> $fooInt=[ordered]@{}
PS C:\> $fooInt.add(12,1)
PS C:\> $fooInt.add(24,2)
PS C:\> write-host ("first item=" + $fooInt.Item([object]12))
first item=1
它也适用于索引:
PS C:\> write-host ("first item=" + $fooInt[[object]12])
first item=1
这与 TheIncorrigible1 的实验非常接近,除了您不需要定义字典并将其键入为其他内容,然后将查找转换为匹配类型,您只需要通过转换为对象来访问它,因为您定义的键已经在内部发生了。