Assoc++ Functions

Here are two functions which may be used to increment the associated value of a key in an association list, or a nested key as part of a hierarchy of keys in a nested association list.

Such functions are useful when counting the number of occurrences of items in a set, or when counting items which are dependent upon other items for which a key hierarchy must be used to create a nested association list.

Assoc++

Function Syntax (LM:assoc++ <key> <lst>)
Current Version 1.0
Donate
Arguments
Symbol Type Description
key List or Atom Key of element in association list
lst List Association list
Returns
Type Description
List Association list with key incremented or added

Program Description

This function will increment the associated value of a supplied key if present in a supplied association list; else the key is added to the association list with an associated value of 1.

As demonstrated by the example program found below, this function may be used to count the number of occurrences of distinct items in a set; such as: counting the number of distinct blocks in a drawing; counting the number of distinct strings in a drawing; or counting attribute values.

Since the function utilises the assoc function to attempt to retrieve the supplied key, the key argument is identical to that required by the assoc function and can hence be of any AutoLISP data type.

Select all
;; Assoc++  -  Lee Mac
;; Increments the value of a key in an association list if present, else adds key to the list.
;; key - [any] Key of an element in the list
;; lst - [lst] Association list (may be nil)

(defun LM:assoc++ ( key lst / itm )
    (if (setq itm (assoc key lst))
        (subst (cons key (1+ (cdr itm))) itm lst)
        (cons  (cons key 1) lst)
    )
)

Example Function Call

_$ (LM:assoc++ "key2" '(("key1" . 3) ("key2" . 1) ("key3" . 4)))
(("key1" . 3) ("key2" . 2) ("key3" . 4))

Example of Usage in a Program

This simple example will return an association list detailing the quantities of each block in a drawing. The association list is compiled using the Assoc++ function, using the name of each distinct block as the key for each list item.

If the name of a block is not present in the association list, a new key is added with a count of 1; otherwise the associated value of the existing key is incremented, counting the occurrence of the block.

Select all
(defun c:test ( / a b c )
    (if (setq a (ssget "_X" '((0 . "INSERT"))))
        (repeat (setq b (sslength a))
            (setq c (LM:assoc++ (cdr (assoc 2 (entget (ssname a (setq b (1- b)))))) c))
        )
    )
)

Nested Assoc++

Function Syntax (LM:nassoc++ <key> <lst>)
Current Version 1.0
Donate
Arguments
Symbol Type Description
key List List of lists or atoms representing keys
lst List Association list
Returns
Type Description
List Association list with key incremented or added

Program Description

This function will increment the associated value of a key as part of a key hierarchy, if present in an association list with possible nested structure. If the key hierarchy is not present in the association list, all child keys are added concluding with a key with associated value of 1.

This functionality may be used to count occurrences of items dependent upon other items; such as counting dynamic blocks by name, then by visibility state for each block name.

Similar to the above Assoc++ function, this function uses the assoc function to retrieve each key at each level in the hierarchy, hence each item in the supplied list of keys may be of any AutoLISP data type.

Select all
;; Nested Assoc++  -  Lee Mac
;; Increments the value of a key in an association list with possible nested structure,
;; or adds the set of keys to the list if not present.
;; key - [lst] List of keys & subkeys
;; lst - [lst] Association list (may be nil)

(defun LM:nassoc++ ( key lst / itm )
    (if key
        (if (setq itm (assoc (car key) lst))
            (subst (cons (car key) (LM:nassoc++ (cdr key) (cdr itm))) itm lst)
            (cons  (cons (car key) (LM:nassoc++ (cdr key) nil)) lst)
        )
        (if lst (list (1+ (car lst))) '(1))
    )
)

Example of Usage

_$ (setq alist (LM:nassoc++ '("Item1" "SubItem1" "A") alist))
(
    ("Item1"
        ("SubItem1"
            ("A" 1)
        )
    )
)

_$ (setq alist (LM:nassoc++ '("Item1" "SubItem1" "B") alist))
(
    ("Item1"
        ("SubItem1"
            ("B" 1)
            ("A" 1)
        )
    )
)

_$ (setq alist (LM:nassoc++ '("Item1" "SubItem2" "A") alist))
(
    ("Item1"
        ("SubItem2"
            ("A" 1)
        )
        ("SubItem1"
            ("B" 1)
            ("A" 1)
        )
    )
)

_$ (setq alist (LM:nassoc++ '("Item2" "SubItem1" "A") alist))
(
    ("Item2"
        ("SubItem1"
            ("A" 1)
        )
    )
    ("Item1"
        ("SubItem2"
            ("A" 1)
        )
        ("SubItem1"
            ("B" 1)
            ("A" 1)
        )
    )
)

_$ (setq alist (LM:nassoc++ '("Item1" "SubItem1" "A") alist))
(
    ("Item2"
        ("SubItem1"
            ("A" 1)
        )
    )
    ("Item1"
        ("SubItem2"
            ("A" 1)
        )
        ("SubItem1"
            ("B" 1)
            ("A" 2)
        )
    )
)

Example of Usage in a Program

See my Dynamic Block Counter program which counts blocks by Block Name, then by Visibility State - a two level hierarchy of keys:

(
    ("Block Name 1"
        ("State 1" . 2)
        ("State 2" . 4)
        ("State 3" . 1)
    )
    ("Block Name 2"
        ("State 1" . 3)
        ...
        ("State N" . 2)
    )
    ...
)

textsize

increase · reset · decrease

Designed & Created by Lee Mac © 2010