Rita Pereira
Rita Pereira

Reputation: 61

Remove element from a list with a specific id lisp

I'm trying to do a function in lisp that removes an element from a board given a specific id. My board is a two-dimension array, and in each position I have something like this: (value (id x y)(id x y)...(id x y)). I have to delete every (id x y) triplet in which the id equals the int given in the function call.
I've come up with a probably very bad solution which copies the content of the board into a new one, except the elements that have the specified id. I've tried running a few examples on the console and it returns the correct result but it doesn't change the contents of the array. Isn't the set at the end of the function supposed to do exactly that? Also, I was expecting that the console result would be Tor NILand not the modified board...

(defun remove-id (board int)
  (let ((lin (board-lines board))
        (col (board-columns board)))
    (let ((new-board (new-board lin col)))
      (dotimes (i lin)
        (dotimes (j col)
          (when (not (null (aref board i j)))
            (dolist (el (rest (aref board i j))
              (if (not (= (el-id el) int))
                (copy-content new-board (el-x el)(el-y el)))))))
      (setf board (copy-board new-board)))))

All of the functions that I'm using work correctly, I hope the names are self-explanatory.

Upvotes: 0

Views: 298

Answers (1)

sds
sds

Reputation: 60004

I think what you are looking for is the remove nondestructive family of functions or the delete destructive family. One of them can replace your dolist loop.

More specifically, you need to do something like

(setf (board-content new-board x y) 
      (remove int (board-content old-board x y) :key #'car))

The important parts are

  1. the :key argument (otherwise you are comparing int with (id ...), not with id)
  2. the setf call (since remove does not modify its sequence argument)

(note also that you can replace your two lets with a single let*).

Upvotes: 1

Related Questions