通过哈希循环,或在PowerShell中使用数组
我正在使用这段(简化的)代码从SQL Server中提取一组表 它工作得很好,但现在有些表需要通过视图提取,有些则不需要。所以我需要这样的数据结构:通过哈希循环,或在PowerShell中使用数组,powershell,dictionary,hashtable,Powershell,Dictionary,Hashtable,我正在使用这段(简化的)代码从SQL Server中提取一组表 它工作得很好,但现在有些表需要通过视图提取,有些则不需要。所以我需要这样的数据结构: "Page" "vExtractPage" , "ChecklistItemCategory" "ChecklistItemCategory" , "ChecklistItem" "vExtractChecklistItem" 我在看散列,但没有找到任何关于如何循环散列的内容。在这
"Page" "vExtractPage"
, "ChecklistItemCategory" "ChecklistItemCategory"
, "ChecklistItem" "vExtractChecklistItem"
我在看散列,但没有找到任何关于如何循环散列的内容。在这里做什么才是正确的?也许只是使用一个数组,但两个值都用空格分隔
还是我遗漏了一些明显的东西?关于循环散列:
$Q = @{"ONE"="1";"TWO"="2";"THREE"="3"}
$Q.GETENUMERATOR() | % { $_.VALUE }
1
3
2
$Q.GETENUMERATOR() | % { $_.key }
ONE
THREE
TWO
Christian的答案很好,它展示了如何使用
GetEnumerator
方法循环遍历每个哈希表项。还可以使用键
属性循环。以下是一个示例:
$hash = @{
a = 1
b = 2
c = 3
}
$hash.Keys | % { "key = $_ , value = " + $hash.Item($_) }
输出:
key = c , value = 3
key = a , value = 1
key = b , value = 2
c: 3
b: 2
a: 1
c: 3
b: 2
a: 1
Key = c and Value = 1
Key = b and Value = 2
Key = a and Value = 3
Key = a and Value = 3
Key = b and Value = 2
Key = c and Value = 1
脚本不首选速记;它的可读性较差。%{}运算符被视为速记。以下是如何在脚本中实现可读性和可重用性: 变量设置 选项1:GetEnumerator() 注:个人喜好;语法更容易阅读 GetEnumerator()方法将按如下所示执行:
foreach($hash.GetEnumerator()中的h){
写入主机“$($h.Name):$($h.Value)”
}
输出:
key = c , value = 3
key = a , value = 1
key = b , value = 2
c: 3
b: 2
a: 1
c: 3
b: 2
a: 1
Key = c and Value = 1
Key = b and Value = 2
Key = a and Value = 3
Key = a and Value = 3
Key = b and Value = 2
Key = c and Value = 1
选项2:钥匙
密钥方法将按如下所示执行:
foreach($hash.Keys中的h){
写入主机“${h}:$($hash.Item($h))”
}
输出:
key = c , value = 3
key = a , value = 1
key = b , value = 2
c: 3
b: 2
a: 1
c: 3
b: 2
a: 1
Key = c and Value = 1
Key = b and Value = 2
Key = a and Value = 3
Key = a and Value = 3
Key = b and Value = 2
Key = c and Value = 1
补充资料
请小心对哈希表进行排序
可以将其更改为数组:
PS> $hash.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Hashtable System.Object
PS> $hash = $hash.GetEnumerator() | Sort-Object Name
PS> $hash.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
如果您使用的是PowerShell v3,则可以使用JSON而不是哈希表,并将其转换为具有以下特性的对象:
您也可以在不使用变量的情况下执行此操作
@{
‘foo’=222
'巴'=333
‘baz’=444
“qux”=555
}|%getEnumerator |%{
$\u0.key
$\美元价值
}
这里是另一种快速方法,只需使用键作为哈希表的索引即可获得值:
$hash = @{
'a' = 1;
'b' = 2;
'c' = 3
};
foreach($key in $hash.keys) {
Write-Host ("Key = " + $key + " and Value = " + $hash[$key]);
}
我更喜欢在带有管道的枚举器方法上使用此变量,因为您不必在foreach中引用哈希表(在PowerShell 5中测试): 输出:
key = c , value = 3
key = a , value = 1
key = b , value = 2
c: 3
b: 2
a: 1
c: 3
b: 2
a: 1
Key = c and Value = 1
Key = b and Value = 2
Key = a and Value = 3
Key = a and Value = 3
Key = b and Value = 2
Key = c and Value = 1
现在,这并不是故意按值排序的,枚举器只是以相反的顺序返回对象
但由于这是一个管道,我现在可以根据值对从枚举器接收的对象进行排序:
$hash.getEnumerator() | sort-object -Property value -Desc | foreach {
Write-Host ("Key = " + $_.key + " and Value = " + $_.value);
}
输出:
key = c , value = 3
key = a , value = 1
key = b , value = 2
c: 3
b: 2
a: 1
c: 3
b: 2
a: 1
Key = c and Value = 1
Key = b and Value = 2
Key = a and Value = 3
Key = a and Value = 3
Key = b and Value = 2
Key = c and Value = 1
也可以使用子表达式运算符$()进行短遍历,该运算符返回一个或多个语句的结果
$hash = @{ a = 1; b = 2; c = 3}
forEach($y in $hash.Keys){
Write-Host "$y -> $($hash[$y])"
}
结果:
a -> 1
b -> 2
c -> 3
为了可读性,特别是对于像我这样不专注于powershell的开发人员,我同意这种方法更容易阅读,因此可能更适合编写脚本。除了可读性,VertigoRay的解决方案和Andy的解决方案有一个区别{}是
ForEach对象
的别名,与此处的ForEach
语句不同ForEach对象
利用了管道,如果您已经在使用管道,那么管道可以更快。foreach
语句不存在;这是一个简单的循环。@JamesQMurphy我从上面复制并粘贴了@andy arismendi提供的答案;对于这个问题,它是流行的管道解决方案。你的陈述使我最感兴趣,那就是ForEach对象
(又名:%{}
)比ForEach
快;我证明了这并不是更快。我想证明你的观点是否正确;因为我,像大多数人一样,喜欢我的代码以尽可能快的速度运行。现在,您的论点变为并行运行作业(可能使用多台计算机/服务器)。。。当然,这比从单个线程运行一个串联作业要快。干杯@JamesQMurphy我还认为powershell遵循了shell在多个进程之间传输数据流时所提供的传统优势:每个管道阶段都是一个独立的进程,这一简单事实使您获得了自然的并行性(当然,缓冲区可能会耗尽,最终整个管道的运行速度与最慢的进程一样慢)。这不同于管道进程自行决定生成多个线程,这完全取决于进程本身的实现细节。注意:该命令是从Json转换而来的(反之,ConvertTo Json)——只需交换破折号位置。这会得到一个“ForEach对象:无法绑定参数'Process'。无法将“System.String”类型的“getEnumerator”值转换为“System.Management.Automation.ScriptBlock”类型“如何以其他顺序枚举散列?例如,当我想以升序(此处为a…b…c)打印其内容时。这可能吗?为什么$hash.Item($\u)
而不是$hash[$\u]
?@LPrc使用Sort Object方法来实现这一点。本文对此做了很好的解释:您甚至可以只使用$hash.$\u
。如果hashtable包含key='Keys',此方法不起作用。枚举器可以在“any”中返回值顺序,因为它只是迭代底层实现。在本例中,它恰好出现相反的顺序。对于一个计数器示例:$x=@{a=1;z=2};$x.q=3
在这里是按q,a,z“排序的”。[ordered]
属性触发对不同实现的选择。