Этот код и вывод:
>> 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 по-прежнему 0 в # 2)
- Доступ к несуществующему ключу через .Item или () - как в правой части назначения в моем примере кода - добавляет пару ключ / пусто всловарь;для некоторой задачи (например, подсчет частоты) это «работает», потому что Empty обрабатывается как 0 дополнительно или «» в конкатенации строк.Этот небольшой масштаб автовивификации не может использоваться для объектов (нет достойного способа отобразить Empty на любой объект, который придумает программист, и не использовать магию по умолчанию, как в Python или Ruby в VBScript)
- ЕслиВы должны вести словарь именованных объектов и одновременно иметь доступ к имени и его объекту. Вы можете просто написать
Set d(name) = object
- d (name) создаст слот для ключа «name», если необходимо, и назначение Set поместитобъект в соответствующее значение (перезаписывая пустой или «старый» объект («указатель»)).
Если вы добавите некоторые детали о том, чего вы действительно хотите достичь, я хочу добавитьк этому ответу.
Добавлено:
Если вы (логически) работаете над списком ключей с дубликатами и должны добавлять новые объекты в словарь на лету, вы не можете избежать двойногоищите, потому что вам нужно проверить существование (1.0) и назначить (2.0) (возможно, недавно созданный и назначенный (1.5)) объект вашей рабочей переменной (см. / m: a или / m: b в моем примере кода)е).Другие языки с операторами, которые передают значение, могут разрешать что-то вроде
if ! (oBJ = dicX( key )) {
oBJ = dicX( key ) = new ItemType()
}
oBJ.doSomething()
и без Set VBScript против Let abomination что-то вроде
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, но это подчеркивает важность того, чтобы не делать что-то чаще, чем необходимо.