提问人:mario 提问时间:9/1/2017 更新时间:9/1/2017 访问量:173
Powershell 中索引迭代对象的鸭子类型
Duck typing for indexed iteratables in Powershell
问:
有时,与其在集合上进行管道处理,不如按程序循环访问它们会更方便。为了避免区分和/依赖于输入,更一致的键/值处理会很好:$_
$_.Key
$_.Value
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 中四处寻找鸭子类型的原因。
对于哈希和对象,探测 or 是最简单/显而易见的(无论如何都记不清哪个属于哪个):.getIterator
.getEnumerator
switch ($_) {
{ $_.GetEnumerator } { do-loopy }
{ $_.GetIterator } { do-otherloopy }
但是现在我不太确定如何处理这里的数组。在方法中没有一个行为指标真正突出。[array]
.Get()
确实看起来很独特(至少不是 HashTables 或 PSObjects 中的方法),但即使对于类型猜测来说听起来也有点太通用了.Add()
还不如是一个整数方法(?.GetUpperBound()
等等,已经有点太具体了。
那么,有没有一种标准方法可以说“数组”,最好是在其他数字索引值集合之间共享的东西?
答:
1赞
fdafadf
9/1/2017
#1
如果只想匹配数组:
PS> $x = 1..10
PS> $x.GetType().IsArray
True
或者你可以检查是否有整数索引器:
(Get-Member -InputObject $x -Name 'Item' -MemberType 'ParameterizedProperty').Definition -match '\(int index\)'
评论
0赞
mario
9/2/2017
当然是正确的,但不是我想要的。(虽然 IDK,但 Powershell 本身可能会将某种类型猜测浓缩到那里)。- 当然,内省和签名检查很有趣。尽管目标只是测试一个通用名称的方法名称。那么已经特定于列表/数组了吗?(Hash 和 Object 至少没有它。.IsArray
.Item()
1赞
fdafadf
9/2/2017
如果有 .NET 对象,则 ParameterizedProperty 表示它是索引器。匿名索引器生成为 Item,但您还需要检查它是否为整数索引器。所以这有点棘手,但我不知道更好的方法。
评论
.GetUpperBound()
.GetUpperBound
[array]