以下の変更は役に立ちますか?キーを文字列にします。
$a = Get-Eventlog system -newest 100 | Group-Object {
$_.EntryType, $_.Source
} -AsHashTable -AsString
たぶん、あなたはそれを試してみることができます.
答えを更新して、配列を使用して希望どおりにハッシュできなかった理由を説明しますが、文字列は機能します。
基本的に、知っておくべきことが2つあります。
.NET (実際には、実際にはCLR ) には、値セマンティクスを持つものと参照セマンティクスを持つものという概念があります。値セマンティクスは、通常、文字列や数値、"xyz"
、167
(任意の例) などの単純な値を持つものに使用されます。オブジェクトには参照セマンティクスが使用されます。 値のセマンティクスを持つものは、それらの値が同じ場合に等しいと見なされます。 参照セマンティクスを持つものは、まったく同じオブジェクト(メモリ内の同じアドレスにある) でない限り、等しくありません。
1 つの追加のしわ: 値のセマンティクスを持つものは、オブジェクトで表すことができます (これには、ボックス化とボックス化解除と呼ばれるものが含まれますが、私はそれらをそこに投げて、将来の探索を指摘するだけです。今のところは多すぎます)。オブジェクトが値セマンティクスで物事を表現するために使用される場合、使用される基底クラス (実際には構造体だと思います) はSystem.ValueType
であり、 の 2 つの項目を比較するSystem.ValueType
ことは特殊なケースです: 2 つの項目が同じメモリ アドレスになくても、 2 つのオブジェクトに等しい値が含まれている場合、それらは「等しい」と見なされます。
以下の例 (2 つの int と 2 つの配列の比較) を見てください。int がどのように「等しく」、配列が等しくないかを確認してください。
$a = 167; $b = 167; echo $($a.Equals($b)); #prints True
$c = @(167,"xyz"); $d = @(167,"xyz"); echo $($c.Equals($d)); #prints False
任意の .NET (実際には CLR) オブジェクトは、ハッシュ コード値を計算することができます。その値は、オブジェクトをハッシュ キーとして使用している場合に使用されます。関数 GetHashCode() は、アイテムのハッシュ コードを生成します。例:$a = "xyz"; $a.GetHashCode();
あなたが遭遇したことの説明
あなたの質問に関して、上記の 1 と 2 をまとめてみましょう。配列には参照セマンティクスがあるため、2 つの配列オブジェクトを比較することは、2 つの異なるメモリ位置にある 2 つの異なるオブジェクトを比較することであり、それらは等しいとは見なされません。さらに、これはハッシュコードが等しくないことを意味します。
これは、上記の配列を使用して、 2 つの異なるハッシュ コードecho $c.GetHashCode(); echo $d.GetHashCode();
を生成します。
ただし、2 つの値が同一の文字列など、値のセマンティクスを持つものは、実際には同じハッシュ コードを生成します。
$e = "xyz"; $f = "xyz"; echo $e.GetHashCode(); echo $f.GetHashCode();
そのため、キーに対して生成されたハッシュ コードが異なるため、配列によるハッシュは問題を引き起こしました (まったく同じ配列を使用した場合を除き、正しく観察されたもの)。しかし、ハッシュコードが同じであるため、たとえば文字列によるハッシュは問題を回避します。
ファイナルノート
上記の説明の内容を理解するためにこれを知る必要はありませんが、CLR が (一般的に) 行うことの 1 つは、実際には 2 つの値が同一の値の型を作成し、同じオブジェクト (または構造体) にすることです。オブジェクトを介して値の型を表しています。したがって$a = "xyz"; $b = "xyz";
、実際には同じオブジェクトを参照するようになります。つまり、$a は $b と同じオブジェクトです。値が同一であるだけでなく、同一です。この追加情報は、上記の単純化された情報と衝突する必要はありません。