在 powershell 中的有序字典中查找键的索引
finding index of key in an ordered dictionary in powershell
我在 powershell 中使用 hashtables/dictionaries 遇到了一些麻烦。最近的障碍是在有序字典中查找键索引的能力。
- 我正在寻找一种不只是遍历对象的解决方案。
(我已经知道怎么做了)
考虑以下示例:
$dictionary = [Ordered]@{
'a' = 'blue';
'b'='green';
'c'='red'
}
如果这是一个普通数组,我可以使用 IndexOf() 查找条目的索引。
[array]::IndexOf($dictionary,'c').
正常情况下会return2。
不过,如果我尝试使用有序字典,我会得到 -1。
有什么解决办法吗?
编辑:
万一有人读到这篇文章想知道我在说什么。我试图用它来创建一个对象,以一种也具有数字顺序的方式规范化 属性 条目。
我试图将其用于进程状态,例如:
$_processState = [Ordered]@{
'error' = 'error'
'none' = 'none'
'started' = 'started'
'paused' = 'paused'
'cleanup' = 'cleanup'
'complete' = 'complete'
}
如果您能够轻松做到这一点,上面的对象会给 $_processState.error
一个索引值 0 并通过每个条目递增,最后给 $_processState.complete
一个索引值 5。然后如果您通过 "index value" 比较了两个属性,您可以通过简单的运算符查看哪个属性更靠前。例如:
$thisObject.Status = $_processState.complete
If ($thisObject.Status -ge $_processState.cleanup) {Write-Host 'All done!'}
PS > All done!
^^这不能按原样工作,但就是这个想法。这就是我的目标。或者也许可以找到类似 $_processState.complete.IndexNumber()
的东西
拥有这样的对象还可以让您通过索引名称本身分配值,同时标准化选项...
$thisObject.Status = $_processState.paused
$thisObject.Status
PS > paused
不太确定这是当时最好的方法,或者它是否仍然是 PS v5.
中可用的所有自定义 class 选项的最佳方法
字典使用键而不是索引。 OrderedDictionary 结合了 hashtable
和 ArrayList
以在字典中为您提供 order/index-support,但它仍然是字典 (key-based) 集合。
如果您需要获取 OrderedDictionary
(或 hasthable
)中对象的索引,您需要使用 foreach-loop 和一个计数器。示例(应创建为函数):
$hashTable = [Ordered]@{
'a' = 'blue';
'b'='green';
'c'='red'
}
$i = 0
foreach($key in $hashTable.Keys) {
if($key -eq "c") { $i; break }
else { $i++ }
}
这也是它在内部运作的方式。您可以通过阅读 .NET Reference Source
中 OrderedDictionary
的 IndexOfKey
方法的源代码来验证这一点
可以更简单
它可能不会比 Frode F. 的答案更有效,但可能更简洁(内联)只是将散列 table 的 keys
集合放在子表达式中($()
) 然后对结果调用 indexOf。
对于你的散列table...
您的特定表达方式很简单:
$($dictionary.keys).indexOf('c')
...如您所料给出值 2
。这在常规散列 table 上也同样适用……除非散列 table 几乎以任何方式被修改,当然……所以在那种情况下它可能不是很有用。
换句话说
使用这个散列table(它也展示了很多编码方式4
...):
$hashtable = [ordered]@{
sample = 'hash table'
0 = 'hello'
1 = 'goodbye'
[char]'4' = 'the ansi character 4 (code 52)'
[char]4 = 'the ansi character code 4'
[int]4 = 'the integer 4'
'4' = 'a string containing only the character 4'
5 = "nothing of importance"
}
将产生以下 expression/results 对:
# Expression Result
#------------------------------------- -------------
$($hashtable.keys).indexof('5') -1
$($hashtable.keys).indexof(5) 7
$($hashtable.keys).indexof('4') 6
$($hashtable.keys).indexof([char]4) 4
$($hashtable.keys).indexof([int]4) 5
$($hashtable.keys).indexof([char]'4') 3
$($hashtable.keys).indexof([int][char]'4') -1
$($hashtable.keys).indexof('sample') 0
顺便说一句:
[int][char]'4'
等于 [int]52
[char]'4'
的 "value"(量级?)为 52
,但它是一个字符,所以它被用作
...非常喜欢打字系统,它虽然灵活,但如果您不小心,有时会变得非常糟糕。
对于我试图解决的最初问题,一个类似的进程状态,您现在可以使用从 PowerShell v5 开始的枚举。
您使用 Enum 关键字,按名称设置枚举器,并给它们一个整数值。该值可以是任何值,但在此示例中我使用的是从 0 开始的升序值:
Enum _ProcessState{
Error = 0
None = 1
Started = 2
Paused = 3
Cleanup = 4
Complete = 5
Verified = 6
}
#the leading _ for the Enum is just cosmetic & not required
创建枚举后,您可以将其分配给变量。变量的内容将 return 枚举的文本名称,您可以将它们作为整数进行比较。
$Item1_State = [_ProcessState]::Started
$Item2_State = [_ProcessState]::Cleanup
#return state of second variable
$Item2_state
#comparison
$Item1_State -gt $Item2_State
将return:
Cleanup
False
如果你想和return最高的比较:
#sort the two objects, then return the first result (should return the item with the largest enum int)
$results = ($Item1_State,$Item2_State | Sort-Object -Descending)
$results[0]
有趣的是,您还可以对它们进行算术运算,例如:
$Item1_State + 1
$Item1_State + $Item2_State
将return:
Paused
Verified
此处枚举的更多信息:
我在 powershell 中使用 hashtables/dictionaries 遇到了一些麻烦。最近的障碍是在有序字典中查找键索引的能力。
- 我正在寻找一种不只是遍历对象的解决方案。 (我已经知道怎么做了)
考虑以下示例:
$dictionary = [Ordered]@{
'a' = 'blue';
'b'='green';
'c'='red'
}
如果这是一个普通数组,我可以使用 IndexOf() 查找条目的索引。
[array]::IndexOf($dictionary,'c').
正常情况下会return2。
不过,如果我尝试使用有序字典,我会得到 -1。
有什么解决办法吗?
编辑: 万一有人读到这篇文章想知道我在说什么。我试图用它来创建一个对象,以一种也具有数字顺序的方式规范化 属性 条目。
我试图将其用于进程状态,例如:
$_processState = [Ordered]@{
'error' = 'error'
'none' = 'none'
'started' = 'started'
'paused' = 'paused'
'cleanup' = 'cleanup'
'complete' = 'complete'
}
如果您能够轻松做到这一点,上面的对象会给 $_processState.error
一个索引值 0 并通过每个条目递增,最后给 $_processState.complete
一个索引值 5。然后如果您通过 "index value" 比较了两个属性,您可以通过简单的运算符查看哪个属性更靠前。例如:
$thisObject.Status = $_processState.complete
If ($thisObject.Status -ge $_processState.cleanup) {Write-Host 'All done!'}
PS > All done!
^^这不能按原样工作,但就是这个想法。这就是我的目标。或者也许可以找到类似 $_processState.complete.IndexNumber()
的东西拥有这样的对象还可以让您通过索引名称本身分配值,同时标准化选项...
$thisObject.Status = $_processState.paused
$thisObject.Status
PS > paused
不太确定这是当时最好的方法,或者它是否仍然是 PS v5.
中可用的所有自定义 class 选项的最佳方法字典使用键而不是索引。 OrderedDictionary 结合了 hashtable
和 ArrayList
以在字典中为您提供 order/index-support,但它仍然是字典 (key-based) 集合。
如果您需要获取 OrderedDictionary
(或 hasthable
)中对象的索引,您需要使用 foreach-loop 和一个计数器。示例(应创建为函数):
$hashTable = [Ordered]@{
'a' = 'blue';
'b'='green';
'c'='red'
}
$i = 0
foreach($key in $hashTable.Keys) {
if($key -eq "c") { $i; break }
else { $i++ }
}
这也是它在内部运作的方式。您可以通过阅读 .NET Reference Source
中OrderedDictionary
的 IndexOfKey
方法的源代码来验证这一点
可以更简单
它可能不会比 Frode F. 的答案更有效,但可能更简洁(内联)只是将散列 table 的 keys
集合放在子表达式中($()
) 然后对结果调用 indexOf。
对于你的散列table...
您的特定表达方式很简单:
$($dictionary.keys).indexOf('c')
...如您所料给出值 2
。这在常规散列 table 上也同样适用……除非散列 table 几乎以任何方式被修改,当然……所以在那种情况下它可能不是很有用。
换句话说
使用这个散列table(它也展示了很多编码方式4
...):
$hashtable = [ordered]@{
sample = 'hash table'
0 = 'hello'
1 = 'goodbye'
[char]'4' = 'the ansi character 4 (code 52)'
[char]4 = 'the ansi character code 4'
[int]4 = 'the integer 4'
'4' = 'a string containing only the character 4'
5 = "nothing of importance"
}
将产生以下 expression/results 对:
# Expression Result
#------------------------------------- -------------
$($hashtable.keys).indexof('5') -1
$($hashtable.keys).indexof(5) 7
$($hashtable.keys).indexof('4') 6
$($hashtable.keys).indexof([char]4) 4
$($hashtable.keys).indexof([int]4) 5
$($hashtable.keys).indexof([char]'4') 3
$($hashtable.keys).indexof([int][char]'4') -1
$($hashtable.keys).indexof('sample') 0
顺便说一句:
[int][char]'4'
等于[int]52
[char]'4'
的 "value"(量级?)为52
,但它是一个字符,所以它被用作
...非常喜欢打字系统,它虽然灵活,但如果您不小心,有时会变得非常糟糕。
对于我试图解决的最初问题,一个类似的进程状态,您现在可以使用从 PowerShell v5 开始的枚举。
您使用 Enum 关键字,按名称设置枚举器,并给它们一个整数值。该值可以是任何值,但在此示例中我使用的是从 0 开始的升序值:
Enum _ProcessState{
Error = 0
None = 1
Started = 2
Paused = 3
Cleanup = 4
Complete = 5
Verified = 6
}
#the leading _ for the Enum is just cosmetic & not required
创建枚举后,您可以将其分配给变量。变量的内容将 return 枚举的文本名称,您可以将它们作为整数进行比较。
$Item1_State = [_ProcessState]::Started
$Item2_State = [_ProcessState]::Cleanup
#return state of second variable
$Item2_state
#comparison
$Item1_State -gt $Item2_State
将return:
Cleanup
False
如果你想和return最高的比较:
#sort the two objects, then return the first result (should return the item with the largest enum int)
$results = ($Item1_State,$Item2_State | Sort-Object -Descending)
$results[0]
有趣的是,您还可以对它们进行算术运算,例如:
$Item1_State + 1
$Item1_State + $Item2_State
将return:
Paused
Verified
此处枚举的更多信息: