Page 1 of 1

The versatility of using a Map as an index

Posted: Fri Sep 23, 2011 7:24 pm
by netmaestro
Ok, this is not earth-shattering. But in the course of investigating the best way to index an ISAM file I found that a Purebasic map is a very good fit. You can enforce no duplicates by using #PB_Map_ElementCheck (the default), necessary for a primary key index, and allow duplicates by using #PB_Map_NoElementCheck. The doc states, rather incorrectly, that if you add a mapkey that already exists in this way, the first element will be kept but will not be anymore searchable. When I read this I feared that a map might not suffice for an index that allows duplicate keys. But some hacking proves otherwise. In a ForEach loop duplicate keys always appear together and once you do a FindElement() on a key of which there are several dupes, NextMapElement() will return the stored values for each instance of the key in the order of newest to oldest. Maps, perfect for both primary key indexes and secondary indexes alike:

Code: Select all

NewMap country.s()

AddMapElement(country(), "Canada",   #PB_Map_NoElementCheck)
country() = "1"
AddMapElement(country(), "France",   #PB_Map_NoElementCheck)
AddMapElement(country(), "Usa",      #PB_Map_NoElementCheck)
AddMapElement(country(), "Canada",   #PB_Map_NoElementCheck)
country() = "2"
AddMapElement(country(), "Mexico",   #PB_Map_NoElementCheck)
AddMapElement(country(), "Germany",  #PB_Map_NoElementCheck)
AddMapElement(country(), "Denmark",  #PB_Map_NoElementCheck)
AddMapElement(country(), "Canada",   #PB_Map_NoElementCheck)
country() = "3"
AddMapElement(country(), "Mexico",   #PB_Map_NoElementCheck)
AddMapElement(country(), "England",  #PB_Map_NoElementCheck)
AddMapElement(country(), "Ireland",  #PB_Map_NoElementCheck)
AddMapElement(country(), "Scotland", #PB_Map_NoElementCheck)

If FindMapElement(country(),"Canada")
  Debug MapKey(country())+" "+country()
  result = NextMapElement(country())
  While result
    If MapKey(country()) = "Canada"
      Debug MapKey(country()) + " " + country()
    Else
      Break
    EndIf
    result = NextMapElement(country())
  Wend
EndIf

Debug  ""

ForEach country()
  Debug MapKey(country())
Next
As I say, not earth-shattering news but useful information that not everybody will know. I didn't, and the doc is a bit lacking on describing this capability.

Re: The versatility of using a Map as an index

Posted: Fri Sep 23, 2011 10:03 pm
by luis
Hi !
netmaestro wrote: The doc states, rather incorrectly, that if you add a mapkey that already exists in this way, the first element will be kept but will not be anymore searchable.
The missing point is the fact they seem to be near each other and that can be used as shown in your example, and that's good to know, thanks.

But the doc isn't wrong in my opinion. It mention explicitly "direct access".
manual wrote: #PB_Map_NoElementCheck
No element check, so if a previous element with the same key was already present, it
will be not replaced but kept in the map without be reachable with direct access. It will remain unreachable
until the newly added element has been deleted. Such unreachable elements will still be listed when enumerating
all the map elements with ForEach or NextMapElement
If the behavior you found is something we can count on, could be a nice addition to the doc.

Re: The versatility of using a Map as an index

Posted: Fri Sep 23, 2011 10:42 pm
by netmaestro
I don't say the doc is wrong exactly, just a bit misleading. And while it says the dupes are available with NextMapElement() and ForEach, it isn't made clear at all that they will be adjacent. But they are and that's a big bonus.

Re: The versatility of using a Map as an index

Posted: Sat Sep 24, 2011 4:05 am
by Demivec
Thanks for demonstrating what being 'unreachable' meant. I had been under the impression that the previous element was somehow using memory without being able to access it.

The manual definitely needs to be updated, possibly with sample code like your example.

Re: The versatility of using a Map as an index

Posted: Sat Sep 24, 2011 5:46 pm
by kenmo
Yeah, this is an interesting way to use Maps.... useful.

As long as this functionality doesn't change in a future version (I don't see why it would?), this is a good tip to know. Thanks for the demo.