gpt4 book ai didi

powershell - 使用数组作为哈希表中的键

转载 作者:行者123 更新时间:2023-12-04 11:38:09 24 4
gpt4 key购买 nike

数组可以用作哈希表中的键吗?如何使用数组键引用哈希表项?

PS C:\> $h = @{}
PS C:\> $h[@(1,2)] = 'a'
PS C:\> $h

Name Value
---- -----
{1, 2} a # looks like the key is a hash

PS C:\> $h[@(1,2)] # no hash entry
PS C:\> $h.Keys #
1
2
PS C:\> $h[@(1,2)] -eq 'a'
PS C:\> $h[@(1,2)] -eq 'b'
PS C:\> foreach ($key in $h.Keys) { $key.GetType() } # this is promising

IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array

PS C:\> $PSVersionTable.PSVersion.ToString()
7.1.4

最佳答案

虽然您可以使用数组作为哈希表键,但这样做是不切实际的 :

  • 您将使用与键和以后查找完全相同的数组实例。
  • 原因是数组,它是 的实例.NET reference types (相对于 value types,例如整数),使用 .GetHashCode() 的默认实现方法 返回一个哈希码(在哈希表中使用),以及这个默认实现 为每个实例返回不同的代码 - 即使对于直觉上认为“相同”的两个数组实例。
  • 换句话说:尝试将任何此类 .NET 引用类型的实例用作哈希表键(包括其他集合类型)时,您会遇到同样的问题 - 除非给定类型碰巧有自定义 .GetHashCode()根据其内容明确认为不同实例相等的实现。

  • 此外,它使用 PowerShell 的索引器语法( [...] )很尴尬,因为数组实例必须嵌套,一元形式为 , , array constructor operator .但是,点符号(属性访问)照常工作。

  • $h = @{}

    # The array-valued key.
    $key = 1, 2

    $h[$key] = 'a'

    # IMPORTANT:
    # The following lookups work, but only because
    # the *very same array instance* is used for the lookup.

    # Nesting required so that PowerShell doesn't think that
    # *multiple* keys are being looked up.
    $h[, $key]

    # Dot notation works normally.
    $h.$key

    # Does NOT work, because a *different array instance* is used.
    $h.@(1,2)
    A 简单测试给定的表达式是否每次都导致相同的哈希表查找,因此适合作为键 是拨打 .GetHashCode() 方法 反复对它;只有在每次(在给定 session 中)都返回相同的数字时,才能使用该表达式:
    # Returns *different* numbers.
    @(1, 2).GetHashCode()
    @(1, 2).GetHashCode()
    检查 给定的对象或类型是否是(的实例) .NET 引用类型与值类型 :
    # $false is returned in both cases, confirming that the .NET array 
    # type is a *reference type*
    @(1, 2).GetType().IsValueType
    [Array].IsValueType

    解决方法:
    解决方法是 使用数组的字符串表示,尽管提出唯一(足够)的可能是一个挑战 .
    最简单 案例,使用 PowerShell 的字符串插值 , 将数组表示为以空格分隔的元素(字符串化)值列表;例如 "$(1, 2)"逐字产生 1 2 :
    $h = @{}

    # The array to base the key on.
    $array = 1, 2

    # Use the *stringified* version as the key.
    $h["$array"] = 'a'

    # Works, because even different array instances with equal-valued
    # instances of .NET primitive types stringify the same.
    # '1 2'
    $h["$(1, 2)"]
    iRon指出这种简单化的方法 会导致歧义 (例如,单个 '1 2' 字符串将产生与数组 1, 2 相同的键)并建议改为:

    a more advanced/explicit way for array keys would be:

    • joining their elements with a non-printable character; e.g.
      $key = $array -join [char]27
    • or, for complex object array elements, serializing the array:
      $key = [System.Management.Automation.PSSerializer]::Serialize($array)

    请注意,即使是 System.Management.Automation.PSSerializer 提供的基于 XML(字符串)的序列化类(在 PowerShell 远程处理和后台作业中用于跨进程编码(marshal)处理)在可靠区分实例方面有其局限性,因为它的递归深度是有限的 - 参见 this answer想要查询更多的信息;您可以按需增加深度,但这样做会导致非常大的字符串表示。
    一个具体的例子:
    using namespace System.Management.Automation

    $ht = @{}

    # Use serialization on an array-valued key.
    $ht[[PSSerializer]::Serialize(@(1, 2))] = 'a'

    # Despite using a different array instance, this
    # lookup succeeds, because the serialized representation is the same.
    $ht[[PSSerializer]::Serialize(@(1, 2))] # -> 'a'

    关于powershell - 使用数组作为哈希表中的键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69335136/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com