Counting in a list using vl-remove-if

Discussion in 'AutoCAD' started by river6822, Aug 17, 2004.

  1. river6822

    river6822 Guest

    After searching the posts I found that some one posted this piece of code.

    (length (vl-remove-if '(lambda (x)(/= x text-value)) text-list))

    I can't seem to get it to work - I'm new to the vl commands.

    (setq lst '(a b b b c c d e e f f f g h i i i j))
    (length (vl-remove-if '(lambda (x)(/= x "a")) lst))

    I'm trying to count each occurance in the list to form a quantity for each item in that list.

    thanks
     
    river6822, Aug 17, 2004
    #1
  2. Your list was composed of symbols, not strings.

    (vl-load-com)
    (setq lst '("a" "b" "b" "b" "c" "c" "d" "e" "e" "f" "f" "f" "g" "h" "i" "i"
    "i" "j"))
    (length (vl-remove-if '(lambda (x)(/= x "a")) lst))


    --
    R. Robert Bell


    After searching the posts I found that some one posted this piece of code.

    (length (vl-remove-if '(lambda (x)(/= x text-value)) text-list))

    I can't seem to get it to work - I'm new to the vl commands.

    (setq lst '(a b b b c c d e e f f f g h i i i j))
    (length (vl-remove-if '(lambda (x)(/= x "a")) lst))

    I'm trying to count each occurance in the list to form a quantity for each
    item in that list.

    thanks
     
    R. Robert Bell, Aug 17, 2004
    #2
  3. river6822

    river6822 Guest

    so if my list were to contain mixed part numbers like 036-010-05 - would I be searching for strings or symbols? and how would the code change to accomodate? Currently the part numbers are NOT contained within quotes.
     
    river6822, Aug 17, 2004
    #3
  4. river6822

    MP Guest

    depends on how you're gathering the part numbers into your list

    "Currently the part numbers are NOT contained within quotes."

    what does that mean?

    depends on how you're looking at it (via princ statement, message box, etc)
    you may or may not "see" the quotes but that data 036-010-05 etc is almost
    certainly a string since it's not a real or an integer

    it' *could* be a symbol but I doubt that's the case
    if so, (vl-symbol-name '036-010-05) would return a string
    "036-010-05"
    assuming you had done something like (setq 036-010-05 "test")
    like I say, that's probably unlikely

    my uneducated guess is they're block names and in that case certainly are
    strings
    maybe you need to provide more info on what your'e trying to do

    be searching for strings or symbols? and how would the code change to
    accomodate? Currently the part numbers are NOT contained within quotes.
     
    MP, Aug 17, 2004
    #4
  5. river6822

    river6822 Guest

    Yes they are not block names, but attached via xdata. So I'm constructing a list of each of the part numbers. That list currently writes a file. What I'm trying to do is allow the file to be written with quantities instead of listing the same part number 3 or 4 times. So they are indeed strings and that makes the difference the results I'm seeing.

    I'm really unclear as to how the "LAMBDA" section of the code works and that's where I get lost. If you could explain that.....

    Thanks
     
    river6822, Aug 17, 2004
    #5
  6. river6822

    MP Guest

    lambda just defines an 'unnamed' function on the fly and executes it
    look at the help files - they pretty much explain all the functions and how
    they work

    '(lambda (x)
    (/= x text-value))
    here the lambda function takes one argument "x" and compares it to
    text-value
    the /= returns T if they are not equal

    this is the same as if you had defined a function
    (defun compareX (x)
    (/= x text-value))
    but since it's just a temporary operation theres no need to define the
    named function and that's why lambda is used

    it's often used in conjunction with Mapcar for similar reason
    hth
    Mark


    a list of each of the part numbers. That list currently writes a file. What
    I'm trying to do is allow the file to be written with quantities instead of
    listing the same part number 3 or 4 times. So they are indeed strings and
    that makes the difference the results I'm seeing.
    that's where I get lost. If you could explain that.....
     
    MP, Aug 17, 2004
    #6
  7. My advice is to not use (vl-remove-if) to just count
    elements in a list.

    (vl-remove-if) is destructive (e.g., it returns a newly
    allocated _copy_ of the input list, with the specified
    elements removed).

    If you need to repeatedly count different items, using
    (vl-remove-if) repeatedly on the same list, you will be
    creating a modified copy of it each time, and that will
    involve needless overhead.

    If your operation is read-only, then just use a foreach
    loop to do it, which does not needlessly allocate any
    new data.

    (defun count-items (item lst / result)
    (setq result 0)
    (foreach x lst
    (if (equal item x)
    (setq result (1+ result))
    )
    )
    result
    )
     
    Tony Tanzillo, Aug 17, 2004
    #7
  8. river6822

    John Uhden Guest

    Tony is right. You have to use (vl-remove-if) very carefully.

    This is the first thing that came to my weary mind if you need a count of all
    the items:
    (defun listcount (input / i output)
    (foreach a input
    (setq i 0)
    (or
    (assoc a output)
    (foreach b input
    (and (equal a b)(setq i (1+ i)) nil)
    )
    (setq output (cons (cons a i) output))
    )
    )
    (reverse output)
    )

    So if: (setq raw '("A" 1 "B" 2 "C" 2 "A" 3 "B" 3 3 "A" "C"))

    Then: (setq counted (listcount raw)) returns:
    (("A" . 3) (1 . 1) ("B" . 2) (2 . 2) ("C" . 2) (3 . 3))

    Though Tony's is more direct, you could retrieve any element of the counted list
    by:
    (cdr (assoc "A" counted))
    3
     
    John Uhden, Aug 19, 2004
    #8
Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.