Scripting 脚本编写。字典查找如果不存在,是否仅添加一个关键字搜索?

Scripting 脚本编写。字典查找如果不存在,是否仅添加一个关键字搜索?,scripting,dictionary,vbscript,scripting.dictionary,Scripting,Dictionary,Vbscript,Scripting.dictionary,我正在Scripting.Dictionary中查找键,以确保只向字典中添加一次键(及其项): If MyDict.Exists (Key) Then ' first internal key-value lookup Set Entry=MyDict.Item (Key) ' Second internal key->value lookup else Set Entry=New ItemType MyDict.Add Key,Entry End If ' Now I wo

我正在
Scripting.Dictionary
中查找键,以确保只向字典中添加一次键(及其项):

If MyDict.Exists (Key) Then ' first internal key-value lookup
  Set Entry=MyDict.Item (Key)  ' Second internal key->value lookup
else
  Set Entry=New ItemType
  MyDict.Add Key,Entry
End If
' Now I work on Entry...
Exists
在字典中查找键,
Item()
也会这样做。因此,对于一个逻辑查找操作,我得到了两个键查找。难道没有更好的办法吗

属性的dox是

如果在尝试返回现有项时未找到项,则会出现一个新项 密钥已创建,其对应项保留为空。” ()

这是正确的,即查找不存在的键显然会使该键成为字典的一部分,可能关联项=空。 但是那有什么好处呢我如何使用它将其归结为一个查找操作?
项()
属性调用期间创建键后,如何设置空项?

此代码和输出:

>> Set d = CreateObject("Scripting.Dictionary")
>> WScript.Echo 0, d.Count
>> If d.Exists("soon to come") Then : WScript.Echo 1, d.Count : End If
>> WScript.Echo 2, d.Count
>> d("soon to come") = d("soon to come") + 1
>> WScript.Echo 3, d.Count, d("soon to come")
>>
0 0
2 0
3 1 1
显示:

  • 使用.Exists查找不存在的键时,不会将该键添加到字典中(.Count在#2处仍然为0)
  • 通过.Item或()访问一个不存在的密钥-就像我的示例代码中赋值的右侧一样-将一个密钥/空对添加到字典中;对于某些任务(例如频率计数),此“有效”,因为在字符串串联中,空被视为加法中的0或“”。这个小比例不能用于对象(没有合适的方式将空映射到程序员认为合适的对象,也没有Python或Ruby中的默认魔法)
  • 如果您必须维护命名对象的字典,并且可以同时访问名称及其对象,则只需编写
    Set d(name)=object
    -d(name)将在必要时创建键槽“name”,并且Set赋值将对象放入相应的值中(覆盖空对象或“old”对象(“指针”))
  • 如果你附加一些你真正想要实现的细节,我愿意补充这个答案

    增加:

    如果(逻辑上)处理具有重复项的键列表,并且必须添加新的 对象动态访问字典时,无法避免双重查找,因为 您需要检查是否存在(1.0)并为(2.0)分配(可能是新的) 为您的工作变量创建并分配(1.5))对象(请参见“我的工作”中的/m:a或/m:b 示例代码)。具有传递值的语句的其他语言可能允许 差不多

    if ! (oBJ = dicX( key )) {
       oBJ = dicX( key ) = new ItemType() 
    }
    oBJ.doSomething()
    
    oBJ = dicX( key )
    If IsEmpty( oBJ ) Then
       dicX( key ) = New ItemType
       oBJ = dicX( key ) 
    End If
    
    没有VBScript的设置vs.让讨厌的东西

    if ! (oBJ = dicX( key )) {
       oBJ = dicX( key ) = new ItemType() 
    }
    oBJ.doSomething()
    
    oBJ = dicX( key )
    If IsEmpty( oBJ ) Then
       dicX( key ) = New ItemType
       oBJ = dicX( key ) 
    End If
    
    只会为新元素做额外的工作,但这一切都是白日梦

    如果那些双重查找真的很重要(我怀疑这一点),你能给出一个论点吗 或者证据?),那么程序的总体设计就很重要了。例如: 如果你能把你的工作清单整理好,一切都会变得简单(参见我的工作清单中的/m:c) 样本)。诚然,我仍然不知道这种改变是否可能 对于您的特定任务

    要进行试验的代码:

    Dim dicX  : Set dicX = CreateObject( "Scripting.Dictionary" )
    Dim aKeys : aKeys    = Split( "1 2 3 4 4 3 2 1 5" )
    Dim sMode : sMode    = "a"
    Dim oWAN  : Set OWAN = WScript.Arguments.Named
    If oWAN.Exists( "m" ) Then sMode = oWAN( "m" )
    Dim sKey, oBJ
    Select Case sMode
      Case "a"
        For Each sKey In aKeys
          If Not dicX.Exists( sKey ) Then 
             Set dicX( sKey ) = New cItemType.init( sKey )
          End If
          Set oBJ = dicX( sKey )
          WScript.Echo oBJ.m_sInfo
        Next    
      Case "b"  
        For Each sKey In aKeys
          If IsEmpty( dicX( sKey ) ) Then 
             Set dicX( sKey ) = New cItemType.init( sKey )
          End If   
          Set oBJ = dicX( sKey )
          WScript.Echo oBJ.m_sInfo
        Next    
      Case "c"  
        aKeys = uniqueList( aKeys )
        For Each sKey In aKeys
          Set dicX( sKey ) = New cItemType.init( sKey )
          Set oBJ = dicX( sKey )
          WScript.Echo oBJ.m_sInfo
        Next    
      Case Else
        WScript.Echo "Unknown /m:" & sMode & ", pick one of a, b, c."
    End Select
    WScript.Echo "----------"
    For Each sKey In dicX.Keys
        WScript.Echo dicX( sKey ).m_sInfo
    Next
    
    Dim g_ITCnt : g_ITCnt = 0
    Class cItemType
      Public m_sInfo
      Public Function init( sKey )
        Set init = Me
        g_ITCnt  = g_ITCnt + 1
        m_sInfo  = "Obj for " & sKey & " (" & g_ITCnt & ")"
      End Function   
    End Class ' cItemType
    
    Function uniqueList( aX )
      Dim dicU : Set dicU = CreateObject( "Scripting.Dictionary" )
      Dim vX
      For Each vX in aX
          dicU( vX ) = Empty
      Next    
      uniqueList = dicU.Keys
    End Function
    
    样本输出:

    /m:a
    Obj for 1 (1)
    Obj for 2 (2)
    Obj for 3 (3)
    Obj for 4 (4)
    Obj for 4 (4)
    Obj for 3 (3)
    Obj for 2 (2)
    Obj for 1 (1)
    Obj for 5 (5)
    ----------
    Obj for 1 (1)
    Obj for 2 (2)
    Obj for 3 (3)
    Obj for 4 (4)
    Obj for 5 (5)
    ==================================================
    xpl.vbs: Erfolgreich beendet. (0) [0.07031 secs]
    
    /m:c
    Obj for 1 (1)
    Obj for 2 (2)
    Obj for 3 (3)
    Obj for 4 (4)
    Obj for 5 (5)
    ----------
    Obj for 1 (1)
    Obj for 2 (2)
    Obj for 3 (3)
    Obj for 4 (4)
    Obj for 5 (5)
    ================================================
    xpl.vbs: Erfolgreich beendet. (0) [0.03906 secs]
    
    定时差异可能是由/m:c的输出减少引起的 模式,但它强调了不经常做某事的重要性
    那是必要的

    对我来说,关键问题是VBScript迫使我们对对象使用
    Set
    ,而
    Empty
    不是对象。我过去使用的一个技巧是使用
    Array
    函数为值创建一个临时占位符。然后我可以检查数组,看看值是否是对象。适用于您的示例:

    tempArr = Array(dict.Item(key))
    If IsEmpty(tempArr(0)) Then
        ' new entry
        Set entry = New MyClass
        ' can't use Add because the key has already been implicitly created
        Set dict.Item(key) = entry
    Else
        ' existing entry
        Set entry = tempArr(0)
    End If
    

    不过,在本例中,您并没有取消双重查找,而是将其从“现有条目”案例移到了“新条目”案例。

    >这种小规模的自动激活不能用于对象…我想要实现的是,如果存在现有条目,则获取对该条目的引用,如果不存在,则添加一个新条目,然后在处理结果条目(现有条目或新添加的条目)时,无需在此过程中进行两次键->值查找尝试。@TheBlastOne:对不起,也许我很笨,但我不理解您的要求,特别是当您的示例代码将条目对象(ItemType)从稀薄的空气中拉出时。你怎么填字典?示例代码的上下文是什么?ItemType是空谈,它与对象类型无关。特定上下文是构建表信息的代码,字典为每个QTP表(=键)包含一个自定义对象(=项),其中包含主键(=键)和行ID(=项)的子字典。引用的代码用于检查手头是否已有QTP图纸的自定义对象,如果没有,则创建并添加一个自定义对象。然后,对自定义对象进行操作。所有这些都无关紧要。问题是:对于Scripting.Dictionary,是否可以检索现有项(如果存在)并添加一个(如果不存在),然后在这两种情况下都接收对该项的引用,而不触发多个键->值查找?出于性能原因,我试图避免冗余(双)查找操作。(是的,我正在优化QTP脚本代码:o()是的,我也这么认为。还尝试了在错误恢复下比较对象和空。