Written August 2024
Although ordered map values are stored as strings (varstr;varstr) or as raw bytes (varstr;varx), you can also store numeric values and do arithmetic with them, more or less like you would with a traditional array of numeric (B, I, or F) values. Consider the following comparison of the two approaches:
dimx ary(0), F, auto_extend ! plain numeric array
dimx $omap, ordmap(varstr;varstr) ! ordered map
...
ary(x) = value ! assign a value to element
$omap(key$) = value ! (expanding array as needed)
ary(x) *= 3.5 ! multiply element value by 3.5
$omap(key$) *= 3.5 !
ary(x) += 1 ! add 1 to element value
$omap(x) #+= 1 ! (note #+ to force addition rather than concatenation)
Notes: In the first pair of assignments, the only real difference is the index used: x in one case, which must evaluate to an integer, and key$ in the other. Internally the value will be stored differently (as a floating point variable in one case, and as its string representation in the other), but since string/numeric conversion is easy (and usually automatic), we haven't lost any flexibility. The second pair of multiplication assignments illustrates that point. The ordered map value will be automatically converted to numeric format for the multiplication, and then converted back to string to update the storage.
The third pair of assignments above illustrates two additional considerations. The first is that even though ordered map keys are always treated as strings, there is nothing stopping you from specifying a numeric variable as the index, i.e. $omap(x) instead of $omap(key$); the x in this case will be automatically converted to string, i.e. str$(x). Note that if you iterate over the map, numeric keys will be ordered like strings (e.g. 1,10,100,11,2,29,3,...) rather than numbers (e.g. 1,2,3,10,11,29,100,...), but that doesn't affect direct access to elements. The second consideration is that the + operator acts as concatenation rather than addition when working with strings, but you can force it to act as addition by inserting # in front of the + (e.g. #+= vs. +=). The val() function will not work in this scenario.
Of course the ordered map data structure is more complex and thus not as efficient as the plain array, so even though it can be used in place of the array, it isn't necessarily a good idea. But it becomes attractive in situations where the index values may include non-integers or are a sparsely populated range of integers. For example, a plain array makes sense for counting people by age, but maybe not for counting real estate listings by 5-digit zip code, where the plain array would need to support 99999 elements even if only a few dozen are actually in use for the data set. Switching to the ordered map is a convenient solution in such a case with on little or no change to the code syntax or logic.
See Also