下面的修改有帮助吗?它将键变成字符串。
$a = Get-Eventlog system -newest 100 | Group-Object {
$_.EntryType, $_.Source
} -AsHashTable -AsString
也许你可以试一试。
更新回答,解释为什么你不能使用数组来散列你想要的方式,但字符串可以工作。
基本上,你需要知道两件事。
.NET(实际上,实际上是CLR)具有具有值语义的事物与具有引用语义的事物的概念。值语义通常用于具有简单值的事物,例如字符串和数字、、"xyz"
和167
(任意示例)。引用语义用于对象。 当它们的值相同时,具有值语义的事物被认为是相等的。 具有引用语义的事物是不相等的,除非它们是完全相同的对象(位于内存中的相同地址)。
额外的皱纹:具有值语义的事物可以由对象表示(这可能涉及称为装箱和拆箱的东西,但我只是将它们放在那里以指向您将来的探索-现在太多了)。当使用对象来表示具有值语义的事物时,使用的基类(我认为实际上是一个结构体System.ValueType
)System.ValueType
是两个对象包含相等的值,它们被认为是“相等的”。
看看下面的例子(比较两个整数与两个数组),它说明了这些事情。看看整数是如何“相等”的,而数组不是。
$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 放在一起。由于数组具有引用语义,因此比较两个数组对象是比较两个不同内存位置的两个不同对象,并且它们不相等。此外,这意味着它们的哈希码将不相等。
使用上面的数组,这echo $c.GetHashCode(); echo $d.GetHashCode();
会产生两个不同的哈希码。
但是,具有值语义的事物,例如两个值相同的字符串,实际上会产生相同的哈希码:
$e = "xyz"; $f = "xyz"; echo $e.GetHashCode(); echo $f.GetHashCode();
因此,数组散列会给您带来问题,因为为键生成的散列码是不同的(除非您使用完全相同的数组,这是您正确观察到的)。但是通过字符串进行散列可以解决问题,因为散列码是相同的。
最后说明
您不需要知道这一点即可获得上述解释的实质内容,但 CLR 将为您做的一件事(通常)实际上是创建两个值相同的值类型,当它们是同一个对象(或结构)时您正在通过对象表示值类型。所以$a = "xyz"; $b = "xyz";
实际上将引用同一个对象,即,$a 与 $b 是同一个对象——它们不仅值相同,而且它们是相同的。此附加信息无需与上述简化信息相冲突。