2016-10-07 49 views
1

私は2つの配列を持っています。私はCOMPARE-OBJECTでいくつかの成功を収めましたが、大きな配列では遅すぎます。この例では、$ ALLVALUESと$ ODDは私の2つの配列です。PowerShellで2つの大きなテキスト配列を比較する

これは、FINDSTR exを使用してこれを効率的に行うことができました。 FINDSTR/V /G:ODD.txt ALLVALUES.txt> EVEN.txt FINDSTRはこれを110,000要素で2秒以内に終了しました。 (ディスクからの読み書きが必要)

私はALLVALUES.txtの中でODD.txtと一致しなかったものすべてを私に与えるFINDSTRのパフォーマンスに戻ろうとしています。このケース)

注:この質問はODDまたはEVENに関するものではなく、必要に応じてすばやく視覚的に確認できる実用的な例です。

ここに私が演奏しているコードがあります。 COMPARE-OBJECTを使って、私のコンピュータ上のFINDSTRに対して200,000秒か2秒かかった。私は、これを行うもっとエレガントな方法があると考えていますPowerShell。ご協力いただきありがとうございます。

# ------- Build the MAIN array 
$MIN = 1 
$MAX = 100000 
$PREFIX = "AA" 

$ALLVALUES = while ($MIN -le $MAX) 
{ 
    "$PREFIX{0:D6}" -f $MIN++ 
} 


# ------- Build the ODD values from the MAIN array 
$MIN = 1 
$MAX = 100000 
$PREFIX = "AA" 

$ODD = while ($MIN -le $MAX) 
{ 
    If ($MIN%2) { 
     "$PREFIX{0:D6}" -f $MIN++ 
    } 
    ELSE { 
    $MIN++ 
    } 
} 

Measure-Command{$EVEN = Compare-Object -DifferenceObject $ODD -ReferenceObject $ALLVALUES -PassThru} 
+0

投稿されたハッシュメソッドは非常に高速です。答えてくれてありがとう!合理的なスピードで検討する他の方法? – BEEBUG

+0

私はCompare-StringArrayを追加し、ハッシュセットコードを改善しました。 – wOxxOm

答えて

4

配列はオブジェクトであり、findstrプロセスのテキストの単純な塊ではありません。
文字列配列の中で最も速い違いは、.NET3.5​​です。

あなたのデータを使用してi7のCPU上の100kの要素のための
$diff = [Collections.Generic.HashSet[string]]$a 
$diff.SymmetricExceptWith([Collections.Generic.HashSet[string]]$b) 
$diffArray = [string[]]$diff 

46ミリ。

上記のコードでは重複する値が省略されているので、出力にそれらの値が必要な場合は、手動の列挙をずっと遅くする必要があります。

function Diff-Array($a, $b, [switch]$unique) { 
    if ($unique.IsPresent) { 
     $diff = [Collections.Generic.HashSet[string]]$a 
     $diff.SymmetricExceptWith([Collections.Generic.HashSet[string]]$b) 
     return [string[]]$diff 
    } 
    $occurrences = @{} 
    foreach ($_ in $a) { $occurrences[$_]++ } 
    foreach ($_ in $b) { $occurrences[$_]-- } 
    foreach ($_ in $occurrences.GetEnumerator()) { 
     $cnt = [Math]::Abs($_.value) 
     while ($cnt--) { $_.key } 
    } 
} 

使用法:HashSetのよりも8倍も遅いが、コンペアオブジェクトより110X速い

$diffArray = Diff-Array $ALLVALUES $ODD 

340ミリ秒、!

そして最後に、我々は、文字列/数値の配列のためのより高速な比較・オブジェクトを行うことができます。

function Compare-StringArray($a, $b, [switch]$unsorted) { 
    $occurrences = if ($unsorted.IsPresent) { @{} } 
        else { [Collections.Generic.SortedDictionary[string,int]]::new() } 
    foreach ($_ in $a) { $occurrences[$_]++ } 
    foreach ($_ in $b) { $occurrences[$_]-- } 
    foreach ($_ in $occurrences.GetEnumerator()) { 
     $cnt = $_.value 
     if ($cnt) { 
      $diff = [PSCustomObject]@{ 
       InputObject = $_.key 
       SideIndicator = if ($cnt -lt 0) { '=>' } else { '<=' } 
      } 
      $cnt = [Math]::Abs($cnt) 
      while ($cnt--) { 
       $diff 
      } 
     } 
    } 
} 

100kの要素を:コンペアオブジェクトよりも早く20-28xは、2100msで完了/ 1460ms(ソートされていない)
10k要素:2〜3倍速く、210ms/162msで完了する(ソートされていません)