3

使用数组键创建散列时,如何生成键来查找散列值。也就是说,没有从哈希的枚举器中获取它

$a = @{"a" = "1"
        "b" = "2"
        ("c","c1") = "3"}

使用常规数组似乎不起作用。

$k1 = @("c","c1")
$a.ContainsKey($k1)  #false

但是,如果在创建时使用数组对象,这似乎可行。

$k1 = @("c","c1")
$a = @{"a" = "1"
     "b" = "2"
 $k1 = "3"}
$a.ContainsKey($k1) #true

例如,如果我用它来生成一个哈希表:

$a = Get-Eventlog system -newest 100 | Group-Object {$_.EntryType, $_.Source } -AsHashTable

我如何自己生成可用于键查找的变量?

4

2 回答 2

4

下面的修改有帮助吗?它将键变成字符串。

$a = Get-Eventlog system -newest 100 | Group-Object {  
    $_.EntryType, $_.Source  
} -AsHashTable -AsString

也许你可以试一试。


更新回答,解释为什么你不能使用数组来散列你想要的方式,但字符串可以工作。

基本上,你需要知道两件事。

  1. .NET(实际上,实际上是CLR)具有具有值语义的事物与具有引用语义的事物的概念。值语义通常用于具有简单值的事物,例如字符串和数字、、"xyz"167(任意示例)。引用语义用于对象。 当它们的值相同时,具有值语义的事物被认为是相等的具有引用语义的事物是不相等的,除非它们是完全相同的对象(位于内存中的相同地址)。
    额外的皱纹:具有值语义的事物可以由对象表示(这可能涉及称为装箱和拆箱的东西,但我只是将它们放在那里以指向您将来的探索-现在太多了)。当使用对象来表示具有值语义的事物时,使用的基类(我认为实际上是一个结构体System.ValueTypeSystem.ValueType是两个对象包含相等的值,它们被认为是“相等的”。
    看看下面的例子(比较两个整数与两个数组),它说明了这些事情。看看整数是如何“相等”的,而数组不是。

    $a = 167; $b = 167; echo $($a.Equals($b)); #prints True
    $c = @(167,"xyz"); $d = @(167,"xyz"); echo $($c.Equals($d)); #prints False

  2. 任何 .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 是同一个对象——它们不仅值相同,而且它们是相同的。此附加信息无需与上述简化信息相冲突。

于 2013-01-22T05:43:14.017 回答
0

这可以接受吗?这是我的哈希表:

$a = @{"Aurillac"="rouge et bleu";"Lyon"="Jaune";"Paris"="Blanc"}

假设$a.keys给出:

Paris
Aurillac
Lyon

寻找$b = "Aurillac","Lyon"as 的键$a是两个数组之间的比较,所以:

$a.Keys | ? {$b -contains $_}
Aurillac
Lyon

或者

$a.Keys | ? {$b -notcontains $_}
Paris

如果你想要一个布尔结果:

($a.Keys | ? {$b -contains $_}) -eq $null
于 2013-01-22T05:02:25.560 回答