Kernel SDK Developer's Guide > Dictionaries of Objects > Iterating through Items of a Dictionary
Iterating through Items of a Dictionary

To iterate through items of a dictionary, use the OdRxDictionaryIterator object which is derived from the OdRxIterator object and inherits its interface. The OdRxDictionaryIterator object has standard iterator behavior and can traverse through a dictionary. The next() method moves the iterator to the end of the dictionary. The done() method checks whether the traversing of the iterator is complete. The iterator refers to the current item of the dictionary for which it returns the required information. The standard iterator declares the object() method that returns the non-typified smart pointer to the instance associated with the item to which the iterator refers. The OdRxDictionaryIterator object declares two specific methods for working with the dictionary — the id() method that returns the ID of the item to which the iterator refers (OdUInt32 value) and the getKey() method that returns the keyword of the item to which the iterator refers (OdString value).

The OdRxDictionary class has a method for creating iterators. To create a new iterator for a dictionary, use the newIterator() method of the OdRxDictionary class which requires the order type of traversing as an argument of the DictIterType type, creates a new iterator, sets it to the first item in the dictionary, and returns the typified smart pointer to a new OdRxDictionaryIterator object that is the iterator. The DictIterType type is the enumeration that defines how the items in the dictionary are stored for traversing — the kDictCollated value performs dictionary traversing in the order of adding of items and the kDictSorted value performs dictionary traversing in keyword alphabetical order.

For example, to iterate through the class dictionary and print the names and IDs of the registered classes in the alphabetical order, use the following code:

void PrintClassKeysIDs()
{
  OdRxDictionaryPtr pClsDict = odrxClassDictionary();

  OdRxDictionaryIteratorPtr it = pClsDict->newIterator(OdRx::kDictSorted);

  while(!it->done())
  {
    odPrintConsoleString(L"\nKey = %s \t [ID = %d]", it->getKey().c_str(), it->id());
    it->next();
  }
}

The result can be following:

Key = AcDb2dPolyline         [ID = 171]
Key = AcDb2dVertex           [ID = 166]
Key = AcDb3dPolyline         [ID = 172]
Key = AcDb3dPolylineVertex   [ID = 167]
Key = AcDb3dSolid            [ID = 194]
Key = AcDbAbstractViewTable  [ID = 151]
Key = AcDbAlignedDimension   [ID = 178]
. . . . . . . . . . . . . . . . . . . .

To get the current instance to which the iterator refers in the dictionary, use the object() method which returns the non-typified smart pointer to this instance. For example, to print the information about registered classes of the class dictionary, use the following code:

void PrintClassInfo()
{
  OdRxClassPtr pClsPtr;

  OdRxDictionaryPtr pClsDict = odrxClassDictionary();

  OdRxDictionaryIteratorPtr it = pClsDict->newIterator(OdRx::kDictCollated);

  while(!it->done())
  {
    pClsPtr = (OdRxClassPtr) it->object();

    odPrintConsoleString(L"\nID = %d, Name = %s, Parent = %s, Flags = %x, DXF = %s, Application = %s", 
                         it->id(), pClsPtr->name().c_str(), pClsPtr->myParent()->name().c_str(),
                         pClsPtr->proxyFlags(), pClsPtr->dxfName().c_str(), pClsPtr->appName().c_str());
    it->next();
  }
}

The result can be following:

ID = 0, Name = OdEdCommandContext, Parent = OdRxObject, Flags = 0, DXF = , Application =
ID = 1, Name = OdEdCommand, Parent = OdRxObject, Flags = 0, DXF = , Application =
ID = 2, Name = OdEdCommandStackReactor, Parent = OdRxObject, Flags = 0, DXF = , Application =
. . . . . . . . . . . . . . . . . . . .
ID = 160, Name = AcDbAttributeDefinition, Parent = AcDbText, Flags = 0, DXF = ATTDEF, Application = AutoCAD 2000
ID = 161, Name = AcDbBlockBegin, Parent = AcDbEntity, Flags = 0, DXF = BLOCK, Application = AutoCAD 2000
ID = 162, Name = AcDbBlockEnd, Parent = AcDbEntity, Flags = 0, DXF = ENDBLK, Application = AutoCAD 2000
. . . . . . . . . . . . . . . . . . . .
ID = 233, Name = AcDbPlaceHolder, Parent = AcDbObject, Flags = 0, DXF = ACDBPLACEHOLDER, Application = ObjectDBX Classes
ID = 234, Name = AcDbVbaProject, Parent = AcDbObject, Flags = 0, DXF = VBA_PROJECT, Application = ObjectDBX Classes
ID = 235, Name = AcDbLayout, Parent = AcDbPlotSettings, Flags = 8000, DXF = LAYOUT, Application = ObjectDBX Classes
. . . . . . . . . . . . . . . . . . . .
ID = 252, Name = AcDbWipeoutVariables, Parent = AcDbObject, Flags = 480, DXF = WIPEOUTVARIABLES, 
          Application = WipeOut|AutoCAD Express Tool|expresstools@autodesk.com
ID = 262, Name = AcDbDimAssoc, Parent = AcDbObject, Flags = 0, DXF = DIMASSOC, Application =      
          "AcDbDimAssoc|AProduct Desc: cDim ARX App For Dimension|Company: Autodesk,Inc.|WEB Address: www.autodesk.com"
ID = 271, Name = AcDbArcAlignedText, Parent = AcDbEntity, Flags = FFF, DXF = ARCALIGNEDTEXT, 
          Application = ATEXT|AutoCAD Express Tool|expresstools@autodesk.com
. . . . . . . . . . . . . . . . . . . .
ID = 324, Name = AcDbRasterImageDef, Parent = AcDbObject, Flags = 8000, DXF = IMAGEDEF, Application = ISM
. . . . . . . . . . . . . . . . . . . .
ID = 437, Name = AcDbRenderEnvironment, Parent = AcDbObject, Flags = 400, DXF =RENDERENVIRONMENT, Application = SCENEOE

An alternate to iterating is getting the number of items in the dictionary using the numEntries() method and modifying a counter from zero up to the number of items minus one. You need to check whether the current value of the counter exists in the dictionary using the has() method and get the smart pointer to the associated instance using the getAt() method. For example:

void PrintClassInfoAlternate()
{
  int id, count;
  OdRxClassPtr pClsPtr;

  OdRxDictionaryPtr pClsDict = odrxClassDictionary();
  
  count = pClsDict->numEntries();

  for(id=0 ; id < count ; id++)
  {
    if(pClsDict->has(id) == true)
    {
      pClsPtr = (OdRxClassPtr) pClsDict->getAt(id);

      if(pClsPtr != NULL)
        odPrintConsoleString(L"\nID = %d, Name = %s, Parent = %s, Flags = %x, DXF = %s, Application = %s", 
                             id, pClsPtr->name().c_str(), pClsPtr->myParent()->name().c_str(),
                             pClsPtr->proxyFlags(), pClsPtr->dxfName().c_str(), pClsPtr->appName().c_str());
    }
  }
}

The result will be the same as in the previous example. However, using iterators is preferred because it allows traversing through the dictionary without validating the number of loops or the current status of items.

See Also

Working with Dictionaries

Functionality of Dictionaries

Example of Working with a Dictionary

Copyright © 2002 – 2020. Open Design Alliance. All rights reserved.