2014-01-18 16 views
7

Array.Findメソッドをpowershellでどのように使用できますか?例えばアレイ。powershell配列を参照

PS> [Array] | Get-Member -Static 

    TypeName: System.Array 

Name   MemberType Definition                      
----   ---------- ---------- 
Find   Method  static T Find[T](T[] array, System.Predicate[T] match) 

は、アレイは、何か他のものにキャストする必要があります。

$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 

いますT []型にマッチさせるには?検索機能を実現する他の方法があることは知っていますが、なぜこれが機能しないのか不思議でした。

答えて

8

ScriptBlockPredicate[T]としてキャストする必要があります。次の例を考えてみましょう:

[Array]::Find(@(1,2,3), [Predicate[int]]{ $args[0] -eq 1 }) 
# Result: 1 

あなたは、エラーを受信し、一致するメソッドオーバーロードを使用すると、PowerShellのScriptBlockに渡している場合には、存在しないためである理由を。 Get-Member出力に書き留めたとおり、Find()メソッドオーバーロードでは、ScriptBlockを2番目のパラメータとして使用できません。 "2":

[Array]::Find(@(1,2,3), { $args[0] -eq 1 }) 

は、 "検索" のための過負荷および引数の数を見つけることができません。 行:1 char:17 + [配列] :: Find(@(1,2,3)、{$ _ -eq 1}) + ~~~~~ +カテゴリ情報:NotSpecified:(:) []、MethodException + FullyQualifiedErrorId:MethodCountCouldNotFindBest

+1

感謝の両方を使用してのSystem.Arrayで600万〜全体の項目を実行する魔法のように動作しました! – NoMoreMrCodeGuy

+0

あなたは大歓迎です!それがうまくいってうれしい。あなたの質問をアップしました。それは良いものです。 –

+0

@Neoliskの答えはこれを行うためのより強力な方法です。 – Cheeso

7

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 } 
+2

-eqも配列演算子として機能するので、それよりも簡単です:$ a -eq 3 – mjolinor

+0

プリミティブではなくオブジェクトに対して比較を行う必要があるため、Array.Findが必要でした。この例は過度に単純化されています。 – NoMoreMrCodeGuy

+2

Neoliskのアプローチは、オブジェクトを使用している場合でも、それを実行する強力な方法です。 Ex。 '$ a |どこで{$ _。MyProperty -eq "Foo"} '。 –

1

別のオプションArrayListを使用することになり、 Contains方法を提供する:

PS C:\>[Collections.ArrayList]$a = 'a', 'b', 'c' 
PS C:\>$a.Contains('b') 
True 
PS C:\>$a.Contains('d') 
False
PS C:\>$a = 'a', 'b', 'c' 
PS C:\>$a -contains 'b' 
True 
PS C:\>$a -contains 'd' 
False
+2

Powershellには '$ a -contains 3'のような' Contains'メソッドもあります。 – Neolisk

1

トレバー・サリバンの答えは、検索()静的メソッドのためだけではなく、正しいものですが、FindIndexのための()にも:@Neoliskはコメントで述べたようまたは、あなたはPowerShellのの-contains演算子を使用することができます。

あなたのサーバー上でアクティブなIPv4の& IPv6の両方でいくつかのNICカードを持って、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で失敗します。誰でもアイデアがありますか?

0

これは、メソッド

$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