在powershell

时间:2016-01-21 16:44:47

标签: powershell dictionary indexing hashtable indexof

我在powershell中使用hashtables / dictionaries有点麻烦。最新的包版是能够在有序字典中找到键的索引。

  • 我正在寻找一种不仅仅是遍历对象的解决方案。我已经知道该怎么做了

考虑以下示例:

$dictionary = [Ordered]@{
    'a' = 'blue';
    'b'='green';
    'c'='red'
    }

如果这是一个普通的数组,我可以使用IndexOf()来查找条目的索引。

[array]::IndexOf($dictionary,'c'). 

在正常情况下,这将返回2.

如果我尝试使用有序字典,我会得-1。

任何解决方案?

编辑: 如果有人读到这个想知道我在说什么。我试图用它来创建一个对象,以一种也有数字顺序的方式规范化属性条目。

我试图将此用于进程的状态,例如:

$_processState = [Ordered]@{
     'error' = 'error'
     'none' = 'none'
     'started' = 'started'
     'paused' = 'paused'
     'cleanup' = 'cleanup'
     'complete' = 'complete'
}

如果你能够轻松地做到这一点,上面的对象会给$_processState.error一个索引值0并在每个条目中上升,最后给$_processState.complete一个索引值5.然后如果你比较两个属性,通过“索引值”,您可以看到哪一个是简单的运算符。例如:

$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中提供的所有自定义类选项的最佳方法。

3 个答案:

答案 0 :(得分:3)

可以更简单

它可能没有比Frode F.的答案更有效,但也许更简洁(内联)只是将哈希表的keys集合放在子表达式中{{1然后在结果上调用indexOf。

对于您的哈希表...

您的具体表达方式很简单:

$()

...按预期给出值$($dictionary.keys).indexOf('c') 。这也适用于常规哈希表...除非哈希表几乎以任何方式被修改,当然......所以它在这种情况下可能不是很有用。

换句话说

使用此哈希表(其中还显示了编码2的许多方法...):

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 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'的(幅度?),但是是一个字符,因此它被用作

...必须喜欢打字系统,如果你不小心的话,它虽然很灵活,但有时会变得非常糟糕。

答案 1 :(得分:2)

字典使用键而不是索引。 OrderedDictionary结合了hashtableArrayList来为字典提供顺序/索引支持,但它仍然是字典(基于密钥)的集合。

如果需要获取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的{​​{1}}方法的源代码来验证这一点

答案 2 :(得分:0)

对于我试图解决的初始问题,一个类似的进程状态,您现在可以使用从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

创建枚举后,您可以将其分配给变量。变量的内容将返回Enum的文本名称,您可以将它们比作整数。

$Item1_State = [_ProcessState]::Started
$Item2_State = [_ProcessState]::Cleanup

#return state of second variable
$Item2_state

#comparison
$Item1_State -gt $Item2_State

将返回:

Cleanup
False

如果你想比较并返回最高:

#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

将返回:

Paused
Verified

有关Enum的更多信息: