Question

Here are my files and functions:

List1.txt => cat dog tiger bear

List2.txt => cat dog tiger

These files are ANSI encoded on winodws xp.

(defun get-file (filename)
  (with-open-file (stream filename)
  (loop for line = (read-line stream nil)
  while line collect line)))

(defparameter *file1* (get-file "list1.txt"))
(defparameter *file2* (get-file "list2.txt"))

(set-difference *file1* *file2*)

I would think the output would be just "bear". However, it returns ("cat", "dog", "tiger", "bear") as the difference. I am assuming it has to due with me reading the information in from files but I was stuck there. Thank you for your time.

Was it helpful?

Solution

Common Lisp uses EQL as default test. You want string-equal or similar.

CL-USER > (set-difference '("cat" "dog" "tiger" "bear")
                          '("cat" "dog" "tiger")
                          :test #'string-equal)
->
("bear")

OTHER TIPS

Apart from the :test keyword parameter of set-difference which Rainer already mentioned, there is another problem in your code. Your function get-file returns a list of lines, where each line is just one string. You probably want to split the lines into words. You can do it easily with split-sequence function (google for the split-sequence Common Lisp package or get it with

(ql:quickload :split-sequence)

if you have quicklisp installed. So, your function could look like, for example:

(defun get-file (path)
  (with-open-file (s path)
    (let* ((len (file-length s))
           (data (make-string len)))
      (read-sequence data s)
      (mapcar #'(lambda (string) (string-trim '(#\Space #\Tab #\Newline) string))
        (split-sequence:split-sequence '#\Space data :remove-empty-subseqs t)))))


(defparameter *file1* (get-file "list1.txt"))
(defparameter *file2* (get-file "list2.txt"))

(format t "~s~%" (set-difference *file1* *file2* :test #'string-equal))

This will, correctly, print:

("bear")
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top