Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/powershell/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cassandra/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么要在PowerShell中使用有序哈希?_Powershell - Fatal编程技术网

为什么要在PowerShell中使用有序哈希?

为什么要在PowerShell中使用有序哈希?,powershell,Powershell,我正在阅读教程,了解到PowerShell支持有序散列。我什么时候可以使用该功能 我所说的示例代码: $hash = [ordered]@{ ID = 1; Shape = "Square"; Color = "Blue"} 订购字典的原因是为了显示/打字。例如,如果您想将哈希表强制转换为a,并且希望密钥按输入顺序排列,则可以使用ordered 这里的用例是当您使用时,标题的顺序是正确的。这只是我脑海中能想到的一个例子。根据设计,hashtable类型与您输入键/值的顺序无关,每次将其显示到成

我正在阅读教程,了解到PowerShell支持有序散列。我什么时候可以使用该功能

我所说的示例代码:

$hash = [ordered]@{ ID = 1; Shape = "Square"; Color = "Blue"}

订购
字典的原因是为了显示/打字。例如,如果您想将
哈希表
强制转换为a,并且希望密钥按输入顺序排列,则可以使用
ordered

这里的用例是当您使用时,标题的顺序是正确的。这只是我脑海中能想到的一个例子。根据设计,
hashtable
类型与您输入键/值的顺序无关,每次将其显示到成功流时都会有所不同

有序
字典的另一个用例是:您可以将哈希表视为数组,并使用数字访问器查找项,例如
$myOrderedHash[-1]
将获取添加到字典中的最后一项。

让我从更广阔的角度补充一下:

tl;dr

  • 大多数情况下,您需要
    [ordered]@{…}
    ()(PSv3+):

    • 它按条目的定义顺序提供条目的枚举(也反映在
      .Keys
      .Values
      集合属性中)
    • 它还允许通过索引访问条目,如数组
  • 通常,您可以将
    [ordered]@{…}
    与常规哈希表
    @{…}
    互换使用,即
    [hashtable]
    a.k.a,因为这两种类型都实现了,这是接受哈希表的参数的典型类型

您因使用
[ordered]
而支付的性能罚款可以忽略不计


一些背景:

出于技术原因,哈希表(哈希表)的最有效实现是让条目的顺序成为实现细节的结果,而不保证调用方的任何特定顺序。

对于只需按键执行独立查找的用例来说,这很好,因为键(条目)之间的顺序是不相关的

但是,您通常关心条目的顺序:

  • 在最简单的情况下,用于显示目的;看到定义顺序混乱令人不安;e、 g:

    @{ one = 1; two = 2; three = 3 } 
    
    Name                           Value
    ----                           -----
    one                            1
    three                          3   # !! 
    two                            2
    
  • 更重要的是,条目的枚举可能需要可预测,以便进行进一步的编程处理;e、 g.(注意:严格来说,属性顺序在JSON中并不重要,但对人类观察者来说同样重要):

不幸的是,PowerShell的哈希表文本语法,
@{…}
,没有默认为
[ordered]
[1],但现在更改已经太晚了。

有一个上下文隐含了
[ordered]
,但是:如果为了创建自定义对象而将哈希表文本强制转换为
[pscustomobject]

[pscustomobject]@{…}
[pscustomobject][ordered]@{…}
的语法糖;也就是说,结果自定义对象的属性是基于哈希表文本中的条目顺序排序的;e、 g:

PS> [pscustomobject] @{ one = 1; two = 2; three = 3 }

one two three  # order preserved!
--- --- -----
  1   2     3
但是,请注意,仅能像上面所示那样工作:如果强制转换直接应用于哈希表文本;如果首先使用变量存储哈希表,或者仅将文本括在
(…)
中,则顺序将丢失:

PS> $ht = @{ one = 1; two = 2; three = 3 }; [pscustomobject] $ht

one three two  # !! Order not preserved.
--- ----- ---
  1     3   2


PS> [pscustomobject] (@{ one = 1; two = 2; three = 3 }) # Note the (...)

one three two  # !! Order not preserved.
--- ----- ---
  1     3   2
因此,如果先迭代构造哈希表,然后将其强制转换为
[pscustomobject]
,则必须从
[ordered]
哈希表开始,以获得可预测的属性顺序;这种技术很有用,因为创建哈希表条目比向自定义对象添加属性更容易;e、 g:

$oht = [ordered] @{} # Start with an empty *ordered* hashtable 
# Add entries iteratively.
$i = 0
foreach ($name in 'one', 'two', 'three') {
  $oht[$name] = ++$i
}
[pscustomobject] $oht # Convert the ordered hashtable to a custom object
最后,请注意,
[ordered]
只能应用于哈希表文本;您不能使用它将先前存在的常规哈希表转换为有序哈希表(无论如何,这没有任何意义,因为您没有定义的开始顺序):

另一方面:当通过管道发送时,有序哈希表和常规哈希表都不会枚举它们的条目;它们作为一个整体发送。
要枚举条目,使用
.GetEnumerator()
方法
;e、 g:

@{ one = 1; two = 2; three = 3 }.GetEnumerator() | ForEach-Object { $_.Value }
1
3  # !!
2

关于使用
[订购]
对性能的影响:

# Ordered hashtable with numeric keys.
PS> $oht = [ordered] @{ 1 = 'one'; 2 = 'two' }

PS> $oht[1]  # same as $oht.1 - interpreted as *index* -> 2nd entry
two

PS> $oht[[object] 1] # interpreted as *key* -> 1st entry.
one
如前所述,它可以忽略不计;以下是一些示例计时,平均10000次运行,使用:

计时示例(Windows 10上的Windows PowerShell 5.1,单核VM):

也就是说,
[ordered]
只造成了5%的减速


[1] InCorrigible1指出了特定于哈希表的一个棘手方面:

# Ordered hashtable with numeric keys.
PS> $oht = [ordered] @{ 1 = 'one'; 2 = 'two' }

PS> $oht[1]  # same as $oht.1 - interpreted as *index* -> 2nd entry
two

PS> $oht[[object] 1] # interpreted as *key* -> 1st entry.
one
使用数字键,区分键和索引可能会变得棘手要强制将数字解释为键,请将其强制转换为
[对象]

# Ordered hashtable with numeric keys.
PS> $oht = [ordered] @{ 1 = 'one'; 2 = 'two' }

PS> $oht[1]  # same as $oht.1 - interpreted as *index* -> 2nd entry
two

PS> $oht[[object] 1] # interpreted as *key* -> 1st entry.
one
也就是说,数字键并不常见,对我来说,默认使用可预测枚举的好处超过了这个小问题

[ordered]
基础的.NET framework类型,即
System.Collections.Specialized.OrderedDictionary
,从v1开始就可以使用,因此PowerShell可以从一开始就选择它作为
@{…}
的默认实现,即使在PowerShell v1中也是如此。
鉴于PowerShell对向后兼容性的承诺,更改默认值不再是一种选择,因为这可能会破坏现有代码。

“不会默认为ordered,但现在更改已经太晚了。”为什么?也就是说,如果它被改变成那样(可能是在某个主要版本中),会有什么坏掉的呢?@hyde:虽然有些东西已经坏掉了,特别是
Command                 TimeSpan         Factor
-------                 --------         ------
$ht=@{one=1;two=2;th... 00:00:00.0000501 1.00  
$ht=[ordered] @{one=... 00:00:00.0000527 1.05  
# Ordered hashtable with numeric keys.
PS> $oht = [ordered] @{ 1 = 'one'; 2 = 'two' }

PS> $oht[1]  # same as $oht.1 - interpreted as *index* -> 2nd entry
two

PS> $oht[[object] 1] # interpreted as *key* -> 1st entry.
one