Powershell中索引可迭代项的Duck类型
与在集合上进行管道连接不同,有时更方便的做法是按程序循环遍历集合。为了避免根据输入区分Powershell中索引可迭代项的Duck类型,powershell,duck-typing,Powershell,Duck Typing,与在集合上进行管道连接不同,有时更方便的做法是按程序循环遍历集合。为了避免根据输入区分$和$键/$值,最好使用更一致的键/值处理: ForEach-KV $object { Param($k, $v); do-stuff } 但是,普通类型的探测有其缺点: #-- iterate over dicts/objects/arrays using scriptblock with Param($k,$v) function ForEach-KV { Param($var, $cb, $i=
$和$键
/$值
,最好使用更一致的键/值处理:
ForEach-KV $object { Param($k, $v); do-stuff }
但是,普通类型的探测有其缺点:
#-- iterate over dicts/objects/arrays using scriptblock with Param($k,$v)
function ForEach-KV {
Param($var, $cb, $i=0)
switch ($var.GetType().Name) {
Array { $var | % { $cb.Invoke($i++, $_) } }
HashTable { $var.Keys | % { $cb.Invoke($_, $var[$_]) } }
"Dictionary``2" { $var.Keys | % { $cb.Invoke($_, $var.Item($_)) } }
PSobject { $var.GetIterator() | % { $cb.Invoke($_.Key, $_.Value) } }
PSCustomObject { $var.GetIterator() | % { $cb.Invoke($_.Key, $_.Value) } }
default { $cb.Invoke($i++, $_) }
}
}
除了那个令人恼火的类型名称之外,这里还有一些重复。这就是我在Powershell中寻找duck打字的原因
对于散列和对象,探测.getIterator
或.getEnumerator
是最简单/明显的方法(无论如何都不太记得哪个属于哪个):
但现在我不太确定如何处理这里的数组。在[array]
s方法中没有一个真正突出的行为指示器
.Get()
看起来确实是独一无二的(至少不是哈希表或PSObject中的方法),但即使对于类型猜测来说,听起来也有点过于泛化
.Add()
也可以是整数方法(?)
.GetUpperBound()
等。已经有点过于具体了
那么,有没有一种标准方法会说“arrayish”,而不是其他数字索引值集合之间共享的东西?如果您只想匹配数组:
PS> $x = 1..10
PS> $x.GetType().IsArray
True
或者您可以检查是否存在整数索引器:
(Get-Member -InputObject $x -Name 'Item' -MemberType 'ParameterizedProperty').Definition -match '\(int index\)'
直到今天才听说鸭子打字。非常酷的概念。.GetUpperBound()
到底有什么问题?你是否只是想专门匹配数组类型,而不是“实现”它的东西?@Matt不,的确如此。我不太精通.NET类型。但是,如果在其他数组样式或列表类型中可以找到.GetUpperBound
,那么这可能是一个很好的限定符。我真的在寻找类似类型的“偶然兼容性”。(虽然在我的情况下我并不需要它。只是想知道,是否/如何可行。)啊,好吧,那么你只想确保它只识别数字索引的[array]
类型,而不是非数组类型的误报。我的问题标题可能会误导你。是的,我主要关心的是普通数组,但这个示例将/应该适用于其他列表类型。查看Set/LinkedList/Stack之类的类型也会类似(可能也有一个隐式索引)。现在,这更多的是关于从KeyValuePair存储区中识别值列表。当然,.IsArray
是正确的,但我要找的不多。(虽然是IDK,但Powershell本身可能会将一些类型猜测浓缩到其中)内省和签名检查当然很有趣。尽管目标只是测试一个常用的命名方法名。那么,.Item()
是否已经特定于列表/数组?(哈希和对象至少没有。)如果您有.NET对象ParameterizedProperty,则表示它是索引器。匿名索引器作为项生成,但您还需要检查它是否为整数索引器。所以这有点棘手,但我不知道更好的方法。
(Get-Member -InputObject $x -Name 'Item' -MemberType 'ParameterizedProperty').Definition -match '\(int index\)'