【问题标题】:array/object keys for hashtables in powershellpowershell中哈希表的数组/对象键
【发布时间】:2013-01-22 01:04:51
【问题描述】:

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

$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

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

【问题讨论】:

    标签: .net powershell clr value-type reference-type


    【解决方案1】:

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

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

    也许你可以试一试。


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

    基本上,您需要了解两件事。

    1. .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

    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 将为您做的一件事(通常)实际上是创建两个值相同的值类型,be 当您通过对象表示值类型时,相同的对象(或结构)。所以$a = "xyz"; $b = "xyz"; 实际上会引用同一个对象,即 $a 和 $b 是同一个对象——它们不仅值相同,而且是相同的。此附加信息无需与上述简化信息相冲突。

    【讨论】:

    • 这确实得到了我正在寻找的东西。但是,我希望知道为什么后期制作的数组不能用作键。
    • @maero:我在上面的答案中添加了一个解释,说明为什么使用数组进行散列对您来说效果不佳。干杯!
    【解决方案2】:

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

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

    假设$a.keys 给出:

    Paris
    Aurillac
    Lyon
    

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

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

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

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

    ($a.Keys | ? {$b -contains $_}) -eq $null
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-06-01
      • 2016-11-18
      • 1970-01-01
      • 2013-07-19
      • 2012-04-10
      • 2018-08-18
      • 2014-12-22
      相关资源
      最近更新 更多