TheSwamp

Code Red => AutoLISP (Vanilla / Visual) => Topic started by: Lee Mac on June 04, 2009, 06:56:08 AM

Title: Too few Arguments (VL-REMOVE-IF)
Post by: Lee Mac on June 04, 2009, 06:56:08 AM
I cannot see why I am having trouble with this code:

Code: [Select]
(setq uniq
        (vl-remove-if
          (function
            (lambda (x y)
              (= (car x) (car y)))) '((1 . 2) (1 . 3) (2 . 4))))

I am trying to remove elements for which the first element is equal, hence the return of the above would be ((2 . 4)).

But I am receiving the error: too few arguments.

Any help is appreciated, thanks.

Lee

Title: Re: Too few Arguments (VL-REMOVE-IF)
Post by: CAB on June 04, 2009, 08:03:55 AM
Try this:
Code: [Select]
(setq uniq nil y nil)
(setq uniq
        (vl-remove-if
          (function
            (lambda (x)
              (cond ((null y) (setq y x))
                    ((= (car x) (car y)))))) '((1 . 2) (1 . 3) (2 . 4))))
Title: Re: Too few Arguments (VL-REMOVE-IF)
Post by: CAB on June 04, 2009, 08:10:50 AM
That doesn't work. Back to the drawing board! :oops:
Title: Re: Too few Arguments (VL-REMOVE-IF)
Post by: Lee Mac on June 04, 2009, 08:17:09 AM
Thanks for your suggestion CAB - your time on this is appreciated  :angel:

I can't see why this is proving such a problem - I thought it would be a no brainer when I wrote it into my code, only to find an error  :-(
Title: Re: Too few Arguments (VL-REMOVE-IF)
Post by: CAB on June 04, 2009, 08:18:35 AM
This returns a unique list, but doesn't eliminate all that have duplicates.
Code: [Select]
(setq uniq nil)

(vl-remove-if
  (function
    (lambda (x)
      (cond ((null uniq) (setq uniq (list x)))
            ((= (car x) (caar uniq)))
            ((setq uniq (cons x uniq)))
      )
    )
  )
  '( (1 . 2) (1 . 3)(2 . 4))
)
Title: Re: Too few Arguments (VL-REMOVE-IF)
Post by: Kerry on June 04, 2009, 08:30:14 AM
not pretty, but seems to work

Code: [Select]
(defun RemoveDupeKeys (MyList / key keylist resultlist)
;;CodeHimBelongs kdub
    (setq resultList MyList
          keyList    (mapcar 'car MyList)
    )
    (while (setq key     (car keyList)
                 keylist (cdr keyList)
           )
        (if (member key keylist)
            (setq resultList
                     (vl-remove-if
                         (function (lambda (x) (= key (car x))))
                         resultList
                     )
            )
        )
    )
    resultList
)

/// kdub

(RemoveDupeKeys '((1 . 2) (1 . 3) (2 . 4) (3 . 4) (4 . 4) (3 . 4) ))

==> ((2 . 4) (4 . 4))
Title: Re: Too few Arguments (VL-REMOVE-IF)
Post by: CAB on June 04, 2009, 08:43:11 AM
Same here. (not pretty)
Code: [Select]
(defun Remove_Car_doups (lst / x result)
  (while (setq x (car lst))
    (setq lst (cdr lst))
    (if (not (vl-some '(lambda (y) (= (car x) (car y))) lst))
      (cond ((null result)(setq result (list x)))
            ((setq result (cons x result))))
    )
    (setq lst (vl-remove-if '(lambda (y) (= (car x) (car y))) lst))
  )
  result
)
Title: Re: Too few Arguments (VL-REMOVE-IF)
Post by: Lee Mac on June 04, 2009, 08:50:52 AM
Many thanks for your solutions guys - although messy by stepping through the list, they do get the job done  :-)

I still can't believe how much coding is needed for a task like this - am I right to believe that vl-remove-if can only take a predicate function with one argument?

Lee
Title: Re: Too few Arguments (VL-REMOVE-IF)
Post by: Kerry on June 04, 2009, 08:59:11 AM
The lambda iterates the list('s) passed in and deals with each item sequentially ..

if you check the help ...
predicate-function
The test function. This can be any function that accepts a single argument and returns T for any user-specified condition. The predicate-function value can take one of the following forms:

A symbol (function name)
'(LAMBDA (A1 A2) ...)
(FUNCTION (LAMBDA (A1 A2) ...))
Title: Re: Too few Arguments (VL-REMOVE-IF)
Post by: Lee Mac on June 04, 2009, 09:30:25 AM
Ah gotcha. Thanks Kerry   8-)
Title: Re: Too few Arguments (VL-REMOVE-IF)
Post by: gile on June 04, 2009, 01:33:04 PM
A recursive way

Code: [Select]
(defun uniq (l)
  (if l
    (if (assoc (caar l) (cdr l))
      (uniq (vl-remove-if '(lambda (x) (= (car x) (caar l))) l))
      (cons (car l) (uniq (cdr l)))
    )
  )
)

EDIT : replace the 'vl-some' statement by an 'assoc' one
Title: Re: Too few Arguments (VL-REMOVE-IF)
Post by: Lee Mac on June 04, 2009, 02:02:04 PM
Very Nice Gile  8-)

I love these Recursive solutions  :-)
Title: Re: Too few Arguments (VL-REMOVE-IF)
Post by: T.Willey on June 04, 2009, 02:07:12 PM
Okay I couldn't resist the challenge.

Code: [Select]
(setq testList '((1 . 2) (1 . 3) (2 . 4)))
(vl-remove-if
    (function
        (lambda ( x / tempList )
            (or
                (and
                    (setq tempList (assoc (car x) testList))
                    (not (equal tempList x))
                )
                (assoc (car x) (cdr (member x testList)))
            )
        )
    )
    testList
)

Returned: ((2 . 4))
Title: Re: Too few Arguments (VL-REMOVE-IF)
Post by: MP on June 04, 2009, 02:08:57 PM
Code: [Select]
[color=green];;  To me problems like this tend to want to distill down to
;;  core problems. Seems to me there are two problems: (1) Find
;;  duplicated keys and (2) remove pairs by specifying the keys.
;;  As such, I tend to form libraries with discrete functions
;;  that perform only one task. Solutions are penned putting
;;  together said singularly minded functions ...[/color]

(defun _FindDuplicatedKeys ( pair_lists / n result )
    (while pair_lists
        (if
            (and
                (assoc (setq key (caar pair_lists)) (setq pair_lists (cdr pair_lists)))
                (null (member key result))
            )
            (setq result (cons key result))
        )
    )    
    result
)

Code: [Select]
[color=green];;  The following is overkill, but in the interests of a
;;  somewhat clean, easy to understand, self documenting
;;  solution ...[/color]

(defun _RemoveByKeys ( pair_lists keys )
    (vl-remove-if
       '(lambda (pair) (member (car pair) keys))
        pair_lists
    )
)

Code: [Select]
[color=green];;  A possible solution ...[/color]

(setq pair_lists '((1 . 2) (1 . 3) (2 . 4)))

(_RemoveByKeys
    pair_lists
    (_FindDuplicatedKeys pair_lists)
)

=> ((2 . 4))

Overkill? Perhaps.
Verbose? Yup.
Re-usable? Me thinks so.

Cheers.
Title: Re: Too few Arguments (VL-REMOVE-IF)
Post by: Lee Mac on June 04, 2009, 02:20:09 PM
MP many thanks for this post -

I always learn such a lot from your well documented functions - great work mate.

Cheers,

Lee
Title: Re: Too few Arguments (VL-REMOVE-IF)
Post by: T.Willey on June 04, 2009, 02:44:12 PM
Man....  :realmad: Michael stole my thunder again....  :cry:









 :wink:
Title: Re: Too few Arguments (VL-REMOVE-IF)
Post by: MP on June 05, 2009, 07:27:13 AM
MP many thanks for this post -

I always learn such a lot from your well documented functions - great work mate.

Cheers,

Lee

Thanks Lee, wish I could spend more time here. Glad to see you've jumped into the fray and have been fully swampified. :)

Man....  :realmad: Michael stole my thunder again....  :cry: :wink:

oops, I did it again? :)