' #############################################################################
' EMULATE AN ASSOCIATIVE ARRAY
' BASED OFF SOME DISCUSSION AT
' https://www.qb64.org/forum/index.php?topic=1001.15
' Tries to emulate a simple dictionary / associative array in QB64.
' Some limitations
' 1. Uses a fixed array size
' 2. Only stores integer values
' 3. Not very efficient (simply appends new keys to the end of the array,
' and searches for them in linear order)
' 4. Requires declaring and passing around 2 arrays
' (one for keys, one for values), instead of a single variable.
' Questions
' 1. Instead of a fixed size, can we implement this with variable arrays and REDIM?
' 2. How can we get it to store mixed data types?
' We could store the values as string, and have a third array of "type",
' but would we have to manually cast each retrieved value with VAL?
' 3. What are some other ways this could be better implemented?
' #############################################################################
' =============================================================================
' GLOBAL DECLARATIONS a$=string, i%=integer, L&=long, s!=single, d#=double
' boolean constants
CONST dKey
= 2, dValue
= 1 ' =============================================================================
' GLOBAL VARIABLES
' =============================================================================
' INITIALIZE
' =============================================================================
' RUN TEST
TestDictionary
' =============================================================================
' FINISH
SYSTEM ' return control to the operating system PRINT ProgramName$
+ " finished."
' /////////////////////////////////////////////////////////////////////////////
REDIM arrKey
(0 TO cMax
, dValue
TO dKey
) AS STRING ' the element 0,1 is the upper limit index
PRINT "-------------------------------------------------------------------------------" PRINT "Initializing dictionary..." InitDictionary arrKey()
'PRINT "arrKey(0,dValue) = " + arrKey(0,dvalue))
PRINT:
PRINT DumpDictionary$
(arrKey
()): WaitForEnter
PRINT "-------------------------------------------------------------------------------" PRINT "Writing some values..."
sKey = "apple": iValue = 3:
bResult = SaveDictionary%(arrKey(), sKey, iValue)
PRINT "SaveDictionary%(arrKey(), " + CHR$(34) + sKey
+ CHR$(34) + ", " + cstr$
(iValue
) + ") returns " + IIFSTR$
(bResult
, "TRUE", "FALSE")
sKey = "africa": iValue = 1:
bResult = SaveDictionary%(arrKey(), sKey, iValue)
PRINT "SaveDictionary%(arrKey(), " + CHR$(34) + sKey
+ CHR$(34) + ", " + cstr$
(iValue
) + ") returns " + IIFSTR$
(bResult
, "TRUE", "FALSE")
sKey = "zebra": iValue = 0:
bResult = SaveDictionary%(arrKey(), sKey, iValue)
PRINT "SaveDictionary%(arrKey(), " + CHR$(34) + sKey
+ CHR$(34) + ", " + cstr$
(iValue
) + ") returns " + IIFSTR$
(bResult
, "TRUE", "FALSE")
sKey = "xylophone": iValue = 2:
bResult = SaveDictionary%(arrKey(), sKey, iValue)
PRINT "SaveDictionary%(arrKey(), " + CHR$(34) + sKey
+ CHR$(34) + ", " + cstr$
(iValue
) + ") returns " + IIFSTR$
(bResult
, "TRUE", "FALSE")
sKey = "zebra": iValue = 4:
bResult = SaveDictionary%(arrKey(), sKey, iValue)
PRINT "SaveDictionary%(arrKey(), " + CHR$(34) + sKey
+ CHR$(34) + ", " + cstr$
(iValue
) + ") returns " + IIFSTR$
(bResult
, "TRUE", "FALSE")
PRINT:
PRINT DumpDictionary$
(arrKey
()): WaitForEnter
PRINT "-------------------------------------------------------------------------------" PRINT "Deleting some keys..."
sKey = "zebra": bResult = DeleteKey%(arrKey(), sKey)
PRINT "DeleteKey%(arrKey(), " + CHR$(34) + sKey
+ CHR$(34) + ") returns " + IIFSTR$
(bResult
, "TRUE", "FALSE")
sKey = "nonesuch": bResult = DeleteKey%(arrKey(), sKey)
PRINT "DeleteKey%(arrKey(), " + CHR$(34) + sKey
+ CHR$(34) + ") returns " + IIFSTR$
(bResult
, "TRUE", "FALSE")
sKey = "xylophone": bResult = DeleteKey%(arrKey(), sKey)
PRINT "DeleteKey%(arrKey(), " + CHR$(34) + sKey
+ CHR$(34) + ") returns " + IIFSTR$
(bResult
, "TRUE", "FALSE")
PRINT:
PRINT DumpDictionary$
(arrKey
()): WaitForEnter
PRINT "-------------------------------------------------------------------------------"
sKey = "africa": iIndex = FoundKey%(arrKey(), sKey)
PRINT "FoundKey%(arrKey(), " + CHR$(34) + sKey
+ CHR$(34) + ") returns " + cstr$
(iIndex
) + " which evaluates to " + IIFSTR$
(iIndex
, "TRUE", "FALSE")
sKey = "xenophobe": iIndex = FoundKey%(arrKey(), sKey)
PRINT "FoundKey%(arrKey(), " + CHR$(34) + sKey
+ CHR$(34) + ") returns " + cstr$
(iIndex
) + " which evaluates to " + IIFSTR$
(iIndex
, "TRUE", "FALSE")
sKey = "APPLE": iIndex = FoundKey%(arrKey(), sKey)
PRINT "FoundKey%(arrKey(), " + CHR$(34) + sKey
+ CHR$(34) + ") returns " + cstr$
(iIndex
) + " which evaluates to " + IIFSTR$
(iIndex
, "TRUE", "FALSE")
sKey = "zambia": iIndex = FoundKey%(arrKey(), sKey)
PRINT "FoundKey%(arrKey(), " + CHR$(34) + sKey
+ CHR$(34) + ") returns " + cstr$
(iIndex
) + " which evaluates to " + IIFSTR$
(iIndex
, "TRUE", "FALSE")
PRINT:
PRINT DumpDictionary$
(arrKey
()): WaitForEnter
PRINT "-------------------------------------------------------------------------------" PRINT "Retrieving values..."
sKey = "africa": iDefault = -1000
PRINT "ReadDictionary%(arrKey(), " + CHR$(34) + sKey
+ CHR$(34) + ", " + cstr$
(iDefault
) + ") returns: " + cstr$
(ReadDictionary%
(arrKey
(), sKey
, iDefault
))
sKey = "zebra": iDefault = -3000
PRINT "ReadDictionary%(arrKey(), " + CHR$(34) + sKey
+ CHR$(34) + ", " + cstr$
(iDefault
) + ") returns: " + cstr$
(ReadDictionary%
(arrKey
(), sKey
, iDefault
))
sKey = "apple": iDefault = -2000
PRINT "ReadDictionary%(arrKey(), " + CHR$(34) + sKey
+ CHR$(34) + ", " + cstr$
(iDefault
) + ") returns: " + cstr$
(ReadDictionary%
(arrKey
(), sKey
, iDefault
))
sKey = "nonesuch": iDefault = -4000
PRINT "ReadDictionary%(arrKey(), " + CHR$(34) + sKey
+ CHR$(34) + ", " + cstr$
(iDefault
) + ") returns: " + cstr$
(ReadDictionary%
(arrKey
(), sKey
, iDefault
))
sKey = "xylophone": iDefault = -5000
PRINT "ReadDictionary%(arrKey(), " + CHR$(34) + sKey
+ CHR$(34) + ", " + cstr$
(iDefault
) + ") returns: " + cstr$
(ReadDictionary%
(arrKey
(), sKey
, iDefault
))
PRINT:
PRINT DumpDictionary$
(arrKey
()): WaitForEnter
PRINT "-------------------------------------------------------------------------------" PRINT "This concludes the test of the pseudo-associative array / dictionary."
WaitForEnter
' /////////////////////////////////////////////////////////////////////////////
INPUT "Press <ENTER> to continue", in$
' /////////////////////////////////////////////////////////////////////////////
' /////////////////////////////////////////////////////////////////////////////
iIndex = 0
FOR iLoop
= 1 TO VAL(arrKey
(0, dValue
)) ' ubound(arrKey) iIndex = iLoop
' KEY EXISTS, UPDATE VALUE
SaveDictionary% = TRUE
' KEY DOESN'T EXIST, ADD IT
' IS THERE ROOM?
iIndex
= VAL(arrKey
(0, dValue
)) + 1 ' DICTIONARY FULL!
SaveDictionary% = FALSE
' ADD VALUE AND KEY
arrKey(iIndex, dKey) = sKey
SaveDictionary% = TRUE
' /////////////////////////////////////////////////////////////////////////////
iIndex = 0
FOR iLoop
= 1 TO VAL(arrKey
(0, dValue
)) ' ubound(arrKey) iIndex = iLoop
FoundKey% = iIndex
' /////////////////////////////////////////////////////////////////////////////
iIndex = 0
FOR iLoop
= 1 TO VAL(arrKey
(0, dValue
)) ' ubound(arrKey) iIndex = iLoop
bResult = FALSE
FOR iLoop
= iIndex
TO (VAL(arrKey
(0, dValue
)) - 1) arrKey(iLoop, dKey) = arrKey(iLoop + 1, dKey)
arrKey(iLoop, dValue) = arrKey(iLoop + 1, dValue)
bResult = TRUE
DeleteKey% = bResult
' /////////////////////////////////////////////////////////////////////////////
sResult = ""
sResult
= sResult
+ "Dictionary size: " + arrKey
(0, dValue
) + CHR$(13) FOR iLoop
= 1 TO VAL(arrKey
(0, dValue
)) ' ubound(arrKey) sResult
= sResult
+ "Item(" + CHR$(34) + arrKey
(iLoop
, dKey
) + CHR$(34) + ") = " + (arrKey
(iLoop
, dValue
)) + CHR$(13) DumpDictionary$ = sResult
' /////////////////////////////////////////////////////////////////////////////
iIndex = 0
FOR iLoop
= 1 TO VAL(arrKey
(0, dValue
)) ' ubound(arrKey) iIndex = iLoop
ReadDictionary% = iDefault
ReadDictionary%
= VAL(arrKey
(iIndex
, dValue
))
' /////////////////////////////////////////////////////////////////////////////
' /////////////////////////////////////////////////////////////////////////////
FUNCTION IIF
(Condition
, IfTrue
, IfFalse
)
' /////////////////////////////////////////////////////////////////////////////
FUNCTION IIFSTR$
(Condition
, IfTrue$
, IfFalse$
) IF Condition
THEN IIFSTR$
= IfTrue$
ELSE IIFSTR$
= IfFalse$
' /////////////////////////////////////////////////////////////////////////////