Associative array for sB
Posted: Sun Apr 21, 2019 9:34 am
Most modern programming languages have an ASSOCIATIVE ARRAY as one of the available data types. It is simply an array in wich the elements are adressable by an alphanumeric key in stead of the numeric keys (0),1,2,3,...,etc.
SmartBasic does not have such data type, but it is rather easy coded, together with the basic operations upon the elements of such an array.
In this sB program, an artificial associative array consists of two normal (string) arrays, one with the actual content and the other with the keys with wich the content may be retrieved.
Each element of the contents array is just one string. It is up to the programmer to decide about the data in that string. Data can be packed into one string using separators and be unpacked with the SPLIT command. One could see one content string as a record in a file. We will name it a record for convenience.
Access is via the keys array. The key of a desired record may be found in the keys array by at least three basic methods:
- by sequentially test each key in the keys array. This is the most simple (and slowest) method.
- By keeping the keys array sorted and use a binary search to find the desired key. This is still a relatively simple method, but much faster whith higher quantities of records.
- By using a hashing algorithm to calculate the physical location of the key in the array. This is the fastest method, but more elaborate due to the handling of synonyms (different keys, which are mapped to the same location by the hashing algoritm)
For now, i have chosen voor the simple, sequential approach. sB is fast enough that a couple of hundred elements in the string do not cause noticable processing times.
You do not have to bother about the array sizes; the size will be extended when needed (keeping their contents of course).
The arrays and the action upon them are kept in one function. The function call to this function is all that the user needs to know:
table$(opcode$,key$,content$),
Where <opcode$> is the specific action to be taken, <key$> is the key under which the content string is to be stored in the array, and <content$> is the info itself.
The opcode must always be present. Use of the other 2 parameters depend on the kind of action.
If the action completes succesfully then, unless stated otherwise, the function return an empty string. If something abnormal happens then an appropiate message string will be returned.
The function calls are:
*** table$ ("init" , "" , content$) *** : initialize the array(s).
Use content$ to pass a filename to be used for saving and loading the array contents. If not necessary, pass the empty string ("").
*** table$ ("add", key$ , content$ ) *** : add content$ to the array under the key value key$. Duplicate key are not permitted, in which case a message "key exists" will be returned
*** content$ = table$ ("get", key$ , "" ) *** : the retrieval action. The record under key value key$ will be returned. If the key does not exist, "not found" will be returned in stead.
*** table$ ("replace" , key$ , content$ ) *** : use for editting a record. content$ is overwriting the content of the record with key value key$. If the key does not exist, "not found" will be returned.
*** table$ ("del", key$ , "" ) *** : the record with key value key$ will be deleted. If the key does not exist, "not found" will be returned.
*** num = table$ ("count" , "" , "" ) *** : returns the number of records in the array (not the size of the array, that is transparant for the user)
*** tabel$ ("save" , "" , "" ) *** : save all info under the filename provided by the "init' call. If no filename is present, "noting saved" is returned.
If a non-existing opcode is entered "unknown opcode" will be returned.
This mechanism is suitable for writing simple apps about one specific object, for instance collections, properties of celestial bodies, a geneology app, etc. In the coming period i will add some tools to it, such as a sorted scrollable list with all keys, a frame for a record display window for viewing and editing. In the next post it will be used to proces a word file, producing strange results.
In my programs it will be linked in with {assoc_array}, wich is the file name under which the code is expected.
SmartBasic does not have such data type, but it is rather easy coded, together with the basic operations upon the elements of such an array.
In this sB program, an artificial associative array consists of two normal (string) arrays, one with the actual content and the other with the keys with wich the content may be retrieved.
Each element of the contents array is just one string. It is up to the programmer to decide about the data in that string. Data can be packed into one string using separators and be unpacked with the SPLIT command. One could see one content string as a record in a file. We will name it a record for convenience.
Access is via the keys array. The key of a desired record may be found in the keys array by at least three basic methods:
- by sequentially test each key in the keys array. This is the most simple (and slowest) method.
- By keeping the keys array sorted and use a binary search to find the desired key. This is still a relatively simple method, but much faster whith higher quantities of records.
- By using a hashing algorithm to calculate the physical location of the key in the array. This is the fastest method, but more elaborate due to the handling of synonyms (different keys, which are mapped to the same location by the hashing algoritm)
For now, i have chosen voor the simple, sequential approach. sB is fast enough that a couple of hundred elements in the string do not cause noticable processing times.
You do not have to bother about the array sizes; the size will be extended when needed (keeping their contents of course).
The arrays and the action upon them are kept in one function. The function call to this function is all that the user needs to know:
table$(opcode$,key$,content$),
Where <opcode$> is the specific action to be taken, <key$> is the key under which the content string is to be stored in the array, and <content$> is the info itself.
The opcode must always be present. Use of the other 2 parameters depend on the kind of action.
If the action completes succesfully then, unless stated otherwise, the function return an empty string. If something abnormal happens then an appropiate message string will be returned.
The function calls are:
*** table$ ("init" , "" , content$) *** : initialize the array(s).
Use content$ to pass a filename to be used for saving and loading the array contents. If not necessary, pass the empty string ("").
*** table$ ("add", key$ , content$ ) *** : add content$ to the array under the key value key$. Duplicate key are not permitted, in which case a message "key exists" will be returned
*** content$ = table$ ("get", key$ , "" ) *** : the retrieval action. The record under key value key$ will be returned. If the key does not exist, "not found" will be returned in stead.
*** table$ ("replace" , key$ , content$ ) *** : use for editting a record. content$ is overwriting the content of the record with key value key$. If the key does not exist, "not found" will be returned.
*** table$ ("del", key$ , "" ) *** : the record with key value key$ will be deleted. If the key does not exist, "not found" will be returned.
*** num = table$ ("count" , "" , "" ) *** : returns the number of records in the array (not the size of the array, that is transparant for the user)
*** tabel$ ("save" , "" , "" ) *** : save all info under the filename provided by the "init' call. If no filename is present, "noting saved" is returned.
If a non-existing opcode is entered "unknown opcode" will be returned.
This mechanism is suitable for writing simple apps about one specific object, for instance collections, properties of celestial bodies, a geneology app, etc. In the coming period i will add some tools to it, such as a sorted scrollable list with all keys, a frame for a record display window for viewing and editing. In the next post it will be used to proces a word file, producing strange results.
In my programs it will be linked in with {assoc_array}, wich is the file name under which the code is expected.
Code: Select all
' pseudo associative array for sB (version april 21, 2019)
' link in with {assoc_array}
'
def table$(opcode$,key$,content$)
if opcode$="init" then
.f$=content$
if file_exists(.f$) then ! load_array(.f$) ! return "" ! end if
N=64 ! .Ntab=N ! dim keys$(N),contents$(N) ! return ""
end if
if opcode$="add" then
for i=1 to N
if keys$(i)=key$ then return "key exists"
next i
adr=find("")
if adr=0 then ! adr=N+1 ! N=expand() ! end if
keys$(adr)=key$ ! contents$(adr)=content$ ! return ""
end if
if opcode$="get" then
adr=find(key$) ! if adr=0 then return "not found"
return contents$(adr)
end if
if opcode$="replace" then
adr=find(key$) ! if adr=0 then return "not found"
contents$(adr)=content$ ! return ""
end if
if opcode$="del" then
adr=find(key$) ! if adr=0 then return "not found"
keys$(adr)="" ! return ""
end if
if opcode$="count" then
num=0
for i=1 to N ! if keys$(i)<>"" then num+=1 ! next i
return num
end if
if opcode$="save" then ! save_array(.f$) ! return "" ! end if
return "unknown opcode"
end def
def load_array(f$)
file f$ input .Ntab ! table$.N=.Ntab
dim table$.keys$(.Ntab),table$.contents$(.Ntab)
for i=1 to .Ntab
file f$ input table$.keys$(i),table$.contents$(i)
next i
end def
def save_array(f$)
if f$="" then return "nothing saved"
if file_exists(f$) then file f$ delete
file f$ print .Ntab
for i=1 to .Ntab
if table$.keys$(i)="" then ! file f$ print """""",""""""
else ! file f$ print table$.keys$(i),table$.contents$(i)
end if
next i
end def
def expand()
n=int(1.5*.Ntab)
dim a$(n),b$(n)
for i=1 to .Ntab
a$(i)=table$.keys$(i) ! b$(i)=table$.contents$(i)
next i
dim table$.keys$(n),table$.contents$(n)
for i=1 to .Ntab
table$.keys$(i)=a$(i) ! table$.contents$(i)=b$(i)
next i
.Ntab=n ! return n
end def
def find(k$)
for i=1 to .Ntab ! if table$.keys$(i)=k$ then break ! next i
if i<=.Ntab then return i else return 0
end def