如何在PowerShell中使用Array.Find方法?
例如:
$a = 1,2,3,4,5
[Array]::Find($a, { args[0] -eq 3 })
给出
Cannot find an overload for "Find" and the argument count: "2".
At line:3 char:1
+ [Array]::Find($a, { $args[0] -eq 3 })
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodCountCouldNotFindBest
数组类具有我期望的方法,如下所示:
PS> [Array] | Get-Member -Static
TypeName: System.Array
Name MemberType Definition
---- ---------- ----------
Find Method static T Find[T](T[] array, System.Predicate[T] match)
是否应该将数组转换为与T []类型匹配的其他内容?我知道还有其他方法可以实现查找功能,但我想知道为什么这不起作用。
答案 0 :(得分:15)
没有必要使用Array.Find,常规where
子句可以正常工作:
$a = @(1,2,3,4,5)
$a | where { $_ -eq 3 }
或者这(由@mjolinor建议):
$a -eq 3
或者这个(返回$true
或$false
):
$a -contains 3
Where
子句支持任何类型的对象,而不仅仅是基本类型,如下所示:
$a | where { $_.SomeProperty -eq 3 }
答案 1 :(得分:9)
您需要将ScriptBlock
转换为Predicate[T]
。请考虑以下示例:
[Array]::Find(@(1,2,3), [Predicate[int]]{ $args[0] -eq 1 })
# Result: 1
您收到错误的原因是,在您传入PowerShell ScriptBlock
的情况下,没有匹配的方法重载。正如您在Get-Member
输出中所述,没有Find()
方法重载接受ScriptBlock
作为其第二个参数。
[Array]::Find(@(1,2,3), { $args[0] -eq 1 })
找不到“查找”和参数计数的重载:“2”。 在行:1 char:17 + [数组] ::查找(@(1,2,3),{$ _ -eq 1}) + ~~~~~ + CategoryInfo:NotSpecified:(:) [],MethodException + FullyQualifiedErrorId:MethodCountCouldNotFindBest
答案 2 :(得分:1)
另一种选择是使用ArrayList
,它提供Contains
方法:
PS C:\> [Collections.ArrayList]$a = 'a', 'b', 'c'
PS C:\> $a.Contains('b')
True
PS C:\> $a.Contains('d')
False
或者,正如@Neolisk在评论中提到的那样,您可以使用PowerShell的-contains
运算符:
PS C:\> $a = 'a', 'b', 'c'
PS C:\> $a -contains 'b'
True
PS C:\> $a -contains 'd'
False
答案 3 :(得分:1)
Trevor Sullivan的答案是正确的,不仅适用于Find()静态方法,也适用于FindIndex()。
当你有多张带有ipv4和amp;的NIC卡时ipv6在您的服务器上处于活动状态并希望检查ipv4 IP /网络掩码对,这样的事情很好:
$NetworkAdapters = Get-WmiObject Win32_NetworkAdapterConfiguration -Filter 'IPEnabled = True' | Select-Object -Property Description, IPAddress, IPSubnet, DefaultIPGateway, DNSServerSearchOrder, DNSDomain
$NetworkAdapters | % {
"Adapter {0} :" -f $_.Description
# array'ing to avoid failure against single homed netcards
$idx = [System.Array]::FindIndex(@($_.IPAddress), [Predicate[string]]{ $args[0] -match "\d+.\d+.\d+.\d+" })
" IP {0} has netmask {1}" -f @($_.IPAddress[$idx]), @($_.IPSubnet)[$idx]
}
我的观点是它在2012 WinPE上的功能就像一个魅力,并且在生产Win7 wks上失败了。有人有想法吗?
答案 4 :(得分:0)
这是使用两种方法在system.array中运行~600万个项目
$s=get-date
$([array]::FindALL($OPTArray,[Predicate[string]]{ $args[0] -match '^004400702(_\d{5})?' })).count
$(New-TimeSpan -Start $s -End $(get-date)).TotalSeconds
20 items
33.2223219 seconds
$s=get-date
$($OPTArray | where { $_ -match '^004400702(_\d{5})?'}).count
$(New-TimeSpan -Start $s -End $(get-date)).TotalSeconds
20 items
102.1832173 seconds