PowerShell数组上的Array.Find

时间:2014-01-18 21:14:07

标签: powershell

如何在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 []类型匹配的其他内容?我知道还有其他方法可以实现查找功能,但我想知道为什么这不起作用。

5 个答案:

答案 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