2017-09-27 19 views
0

別のハッシュテーブルのすべてのプロパティに一致する配列に格納されたハッシュテーブルを返す最適な方法を見つけることを試みています配列から取得します。Powershellのハッシュテーブルの配列に対するハッシュテーブルのプロパティの比較方法

例えば、私は次の配列、およびハッシュテーブル変数があります。

$myarr = @(
    @{"first" = "A";"second" = "B";"third" = "C";"fourth" = "D";"fifth" = "E"}, 
    @{"first" = "M";"second" = "B";"third" = "C";"fourth" = "D";"fifth" = "E";"sixth"="F"}, 
    @{"first" = "A";"second" = "B";"third" = "C";"fourth" = "D";"fifth" = "Z"}) 

$crit = @{"first"="A";"third"="C"} 

を私は$critから[プロパティのすべてが一致した配列に格納されている各全体のハッシュテーブルを返す方法を必要としています。この例では、$myarr[0]$myarr[2]が返されます。

これを実現するには、Properties of $critを1つずつループし、配列内の各ハッシュテーブルと以下のように比較します。ハッシュテーブルを比較するためのより良い方法があるかどうかを確認したいと思います。把握できません。Compare-Objectと似ています。

ForEach ($hash in $myarr) { 
    $match = $true 
    ForEach ($key in $crit.Keys) {If ($hash.$key -ne $crit.$key) {$match = $false;Break}} 
    If ($match) {$hash}} 

このため最終的な目標は、現実世界のアプリケーションはすべて、100を持っている数百のハッシュテーブルを含むこれらの配列の数十万人を、比較されるように、メモリ使用量の最小量との比較を行うことです+プロパティ。当然のことながら、適切な方向への助けがあれば幸いですが、私の目標はこの比較を可能な限り合理化することです。

+0

この1対多の比較プロセスはあり、または多対多の? – mjolinor

+0

@ mjolinor one-to-many; $ myarのような多くの配列と比較して、$ critのような1つのハッシュ。 –

答えて

0

最初にハッシュをオブジェクトに変換します。私はコレクション

  1. コピーし、この条件でフィルタに使用Where-Object
    1. 各条件を超える$result
    2. ループにフルセットをフィルタリング開始後2つの可能なオプション

      $myarr = @(
          @{"first" = "A";"second" = "B";"third" = "C";"fourth" = "D";"fifth" = "E"}, 
          @{"first" = "M";"second" = "B";"third" = "C";"fourth" = "D";"fifth" = "E";"sixth"="F"}, 
          @{"first" = "A";"second" = "B";"third" = "C";"fourth" = "D";"fifth" = "Z"} 
      )|ForEach-Object {New-Object -TypeName psobject -Property $_} 
      
      # or 
      
      $myarr = @(
          [pscustomobject]@{"first" = "A";"second" = "B";"third" = "C";"fourth" = "D";"fifth" = "E"}, 
          [pscustomobject]@{"first" = "M";"second" = "B";"third" = "C";"fourth" = "D";"fifth" = "E";"sixth"="F"}, 
          [pscustomobject]@{"first" = "A";"second" = "B";"third" = "C";"fourth" = "D";"fifth" = "Z"} 
      ) 
      

      を含めました

    3. フィルタリングされた結果を$resultの次のループ

コードは、この

$crit = @{"first"="A";"third"="C"} 

$result=$myarr 
$crit.GetEnumerator()|ForEach-Object { 
    $result=$result|Where-Object -Property $_.Name -EQ $_.Value 
} 
$result 

出力のように見えます

first : A 
second : B 
third : C 
fourth : D 
fifth : E 

first : A 
second : B 
third : C 
fourth : D 
fifth : Z 
+0

私はこのソリューションをテストしてきましたが、これまでのところ私の目的では最適です。私のテストケースはうまくいっていましたが、実際のデータセットを追加すると、正しい結果と「パラメータ 'Property'の引数を検証できませんでした。引数はnullまたは空です.' errors ...私はこれがなぜであるかを正確に特定しようとしています。そして、一度フィルターをかけてしまえば、私はブルートフォースの反復に対するいくつかのベンチマークを得るでしょう。一度私はより多くの結果を持っている、私はおそらく最高の答えとしてこれをマークします。 –

+0

私のソリューションに基づいてキーとプロパティに関してデータが矛盾していることにも気付きました。 'where-object'は、条件キーがプロパティになったハッシュのキーとして存在しないときにエラーをスローするオブジェクトです。特にブルートフォースと比べると、非常に高いパフォーマンスの数字は期待できません。ハッシュをオブジェクトに変換する最初の時間を数えなくても、配管は処理を遅くします。小規模な質問です。データはどこから来ていて、パフォーマンスが重要であるかのように多くのハッシュを生成していますか? –

+0

私は実際には、基準キーが存在せず、エラーを投げなかったシナリオを試しました。これも私の最初の考えの1つでした。このデータは、何百万ものテキストファイルから集められたものです。ファイルのサイズは1キロバイトから1ギガバイトまでの範囲であり、一貫性のない方法で区切られています。私がこれで達成しようとしているのは、作成されたこれらのファイルのすべてのクエリに対して新しい正規表現を書き換えることです。パフォーマンスはボリュームのために問題になるだけでなく、できるだけ多くのスレッド/ジョブを同時に実行できるようにするためです。 –

0

デバイスハッシュテーブルに対して条件をテストする基本機能を次に使用して、Where-Objectを使用してハッシュテーブルの配列をフィルタリングします。

最初の部分については、我々は今、私たちはのは、使用するためにそれを入れてみましょう、2つのハッシュテーブルを比較することができ、この

function Compare-HashtableSubset 
{ 
    param(
    [Parameter(Mandatory,Position=0)] 
    [hashtable]$HashTable, 

    [Parameter(Mandatory,Position=1)] 
    [hashtable]$SubTable 
) 

    foreach($entry in $SubTable.GetEnumerator()) { 
    if((-not $HashTable.ContainsKey($entry.Key)) -or $HashTable[$entry.Key] -ne $entry.Value){ 
     # missing key or value mismatch, we're done here 
     return $false 
    } 
    } 
    # made it to the end, must be good 
    return $true 
} 

ような何かを行うことができます!

PS C:\> $filteredArray = $myarr |Where-Object { Compare-HashtableSubset $_ $crit } 
PS C:\> $filteredArray.Count 
2 
0

このことができますかどうか分からないのですが、あなたはテストセットに対してそれを実行し、ブルートフォースの繰り返しよりも良くスケールかどうかを確認することができます

$myarr = @(
    @{"first" = "A";"second" = "B";"third" = "C";"fourth" = "D";"fifth" = "E"}, 
    @{"first" = "M";"second" = "B";"third" = "C";"fourth" = "D";"fifth" = "E";"sixth"="F"}, 
    @{"first" = "A";"second" = "B";"third" = "C";"fourth" = "D";"fifth" = "Z"}) 

$crit = @{"first"="A";"third"="C"} 

$match1 = '*"first": "A"*' 
$match2 = '*"third": "C"*' 

($myarr |% {$_ | convertto-json}) -like $match1 -like $match2 | convertfrom-json 

あなたがよいか月最後のconvertfrom-jsonは必要ありません。 JSONが受け入れられるような結果が得られれば、それを使わなくてももっと速く動くはずです。 brute-force繰り返しよりも多くのメモリを使用しますが、一度に1つのハッシュテーブルではなく、アレイ全体を一度に実行する必要があります。

+0

私はこのアイデアが大好きですが、私の具体的な目的のためにはうまく調整できません。現実世界のシナリオで行う必要のある試合の数が増えれば、同じステートメントが私にとっては面倒になります。 –

関連する問題