Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't the set difference function compare lists with data from files?

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.

like image 212
user614885 Avatar asked Sep 16 '26 13:09

user614885


2 Answers

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")
like image 73
Rainer Joswig Avatar answered Sep 19 '26 09:09

Rainer Joswig


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")
like image 30
piokuc Avatar answered Sep 19 '26 08:09

piokuc



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!