tutorial español scripting dictionary vbscript scripting.dictionary

scripting - tutorial - solidity español



Scripting.Dictionary Lookup-add-if-not-present con solo una búsqueda de clave? (2)

Este código y salida:

>> 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

muestra:

  1. Buscar una clave no existente con .Exists no agrega la clave al diccionario (.Count sigue siendo 0 en el n. ° 2)
  2. Acceder a una clave no existente a través de .Item o () - como en el lado derecho de la asignación en mi código de muestra - agrega una clave / par vacío al diccionario; para alguna tarea (por ejemplo, conteo de frecuencia) esto ''funciona'', porque Vacío se trata como 0 además o "" en la concatenación de cadenas. Esta autovigilancia a pequeña escala no se puede usar para objetos (no hay una forma decente para asignar Empty a cualquier objeto que el programador piense y ninguna magia predeterminada como en Python o Ruby en VBScript)
  3. Si tiene que mantener un diccionario de objetos nombrados y puede acceder al nombre y a su objeto al mismo tiempo, puede escribir Set d(name) = object - d (name) creará el "nombre" de ranura de clave si es necesario y la asignación de Set colocará el objeto en el valor correspondiente (sobreescribiendo Empty o el objeto ''antiguo'' (''puntero'')).

Si agrega algunos detalles sobre lo que realmente desea lograr, estoy dispuesto a agregar a esta respuesta.

Adicional:

Si (lógicamente) trabaja en una lista de claves con duplicados y debe agregar nuevos objetos al diccionario sobre la marcha, no puede evitar la doble búsqueda, porque necesita verificar la existencia (1.0) y asignar (2.0) la (tal vez el objeto recién creado y asignado (1.5)) a su variable de trabajo (vea / m: a o / m: b en mi código de muestra). Otros lenguajes con declaraciones que entregan un valor pueden permitir algo como

if ! (oBJ = dicX( key )) { oBJ = dicX( key ) = new ItemType() } oBJ.doSomething()

y sin VBScript''s Set vs. Let Abomination algo así como

oBJ = dicX( key ) If IsEmpty( oBJ ) Then dicX( key ) = New ItemType oBJ = dicX( key ) End If

haría el trabajo extra solo por nuevos elementos, pero todo eso es un sueño imposible.

Si esas búsquedas dobles realmente importan (lo que dudo, ¿puede dar un argumento o evidencia?), Entonces el diseño general de su programa sí importa. Por ejemplo: si puede hacer una lista de trabajo única, todo se vuelve simple (vea / m: c en mi ejemplo). Es cierto, todavía no tengo idea, si tales cambios son posibles para su tarea específica.

Código para experimentar con:

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

muestra de salida:

/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]

La diferencia de tiempo es probablemente causada por la salida reducida del modo / m: c, pero enfatiza la importancia de no hacer algo más a menudo de lo necesario.

Estoy buscando claves en un Scripting.Dictionary para asegurarme de que las agregue (y sus elementos) solo una vez al diccionario:

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 busca la clave en el diccionario, y Item () también lo hace. Así que obtengo dos búsquedas clave para una operación de búsqueda lógica. ¿No hay una mejor manera?

La dox para la propiedad del Item dice

"Si no se encuentra la clave al intentar devolver un artículo existente, se crea una nueva clave y su artículo correspondiente se deja vacío". ( MSDN )

Esto es cierto, es decir, buscar una clave inexistente obviamente hace que esta parte clave del diccionario, probablemente con el elemento asociado = vacío. Pero, ¿para qué sirve eso? ¿Cómo podría usar esto para reducirlo a una sola operación de búsqueda? ¿Cómo puedo configurar el elemento vacío después de crear la clave durante la llamada a la propiedad Item () ?


El problema clave para mí es el hecho de que VBScript nos obliga a usar Set con objetos, y Empty no es un objeto. Un truco que he usado en el pasado para evitar esto es usar la función Array para crear un marcador de posición temporal para el valor. Luego puedo verificar la matriz para ver si el valor es un objeto o no. Aplicado a tu ejemplo:

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

Sin embargo, en este caso, no ha eliminado la búsqueda doble, sino que la ha movido del caso de "entrada existente" al caso de "entrada nueva".