6.20.4 Using Maps as Sets

Sometimes, you want a collection of objects of type K that lets you quickly add items, delete items, and determine whether an item is present. In Asymptote, the most straightforward option for such a collection is a Map from keys of type K to bool values, with nullValue set to false.

One needs to access some version of Map_K_bool. If K is hashable, one could write

from collections.hashmap(K=K,V=bool) access
    Map_K_V as Map_K_bool,
    HashMap_K_V as HashMap_K_bool;
Map_K_bool mset = HashMap_K_bool(nullValue=false);

If K is not hashable but does have operator <, something like this may be used instead:

from collections.btreemap(K=K,V=bool) access
    Map_K_V as Map_K_bool,
    BTreeMap_K_V as BTreeMap_K_bool;
Map_K_bool mset = BTreeMap_K_bool(nullValue=false);

To add an item k to mset, assign it the value true:

mset[k] = true;

If the item was already in the set, this statement will have no effect.

To test whether an item is in the set, you can either use the contains method or use brackets to access the value associated with k:

if (mset.contains(k))
  write('membership verified');

or, equivalently,

if (mset[k])
  write('membership verified');

To remove an item from the set, you can either use the delete method (which throws an error if the item was not already present) or set its value to false (which does nothing if the item was not already present):

mset.delete(k);  // guaranteed to reduce mset.size() by 1 or throw an error
mset[k] = false; // would delete k if we had not already deleted it

Once a key has its value set to false, it will not show up in iterators over the set, nor will it contribute to the size() of the set:

mset[k] = true;
int size1 = mset.size();
mset[k] = false;
assert(mset.size() == size1 - 1);

One can iterate over the set or check its size:

int count = 0;
for (K k : mset) { ++count; }
assert(mset.size() == count);