How can I use the Array.Find method in powershell?
For example:
$a = 1,2,3,4,5
[Array]::Find($a, { args[0] -eq 3 })
gives
This was run across ~6 million items in a system.array using both methods
$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
Trevor Sullivan's answer is the right one, not only for Find() static method, but for FindIndex() as well.
When you've got several NIC cards with both ipv4 & ipv6 active on your servers and want to check the ipv4 IP/netmask pairs, something like this is good :
$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]
}
My point is it works like a charm on 2012 WinPE, and fails on a production Win7 wks. Anyone got an idea ?
There is no need to use Array.Find, a regular where clause would work fine:
$a = @(1,2,3,4,5)
$a | where { $_ -eq 3 }
Or this (as suggested by @mjolinor):
$a -eq 3
Or this (returns $true or $false):
$a -contains 3
Where clause supports any type of objects, not just basic types, like this:
$a | where { $_.SomeProperty -eq 3 }
You need to cast the ScriptBlock as a Predicate[T]. Consider the following example:
[Array]::Find(@(1,2,3), [Predicate[int]]{ $args[0] -eq 1 })
# Result: 1
The reason that you received the error, is because there was no matching method overload, in the case where you're passing in a PowerShell ScriptBlock. As you noted in your Get-Member output, there is no Find() method overload that accepts a ScriptBlock as its second parameter.
[Array]::Find(@(1,2,3), { $args[0] -eq 1 })
Cannot find an overload for "Find" and the argument count: "2". At line:1 char:17 + [Array]::Find(@(1,2,3), { $_ -eq 1 }) + ~~~~~ + CategoryInfo : NotSpecified: (:) [], MethodException + FullyQualifiedErrorId : MethodCountCouldNotFindBest
Another option would be using an ArrayList, which provides a Contains method:
PS C:\> [Collections.ArrayList]$a = 'a', 'b', 'c'
PS C:\> $a.Contains('b')
True
PS C:\> $a.Contains('d')
False
Or, as @Neolisk mentioned in the comments, you could use PowerShell's -contains operator:
PS C:\> $a = 'a', 'b', 'c'
PS C:\> $a -contains 'b'
True
PS C:\> $a -contains 'd'
False