Raymond Toy pushed to branch issue-240-add-hashtable-for-destructive-set-ops at cmucl / cmucl

Commits:

2 changed files:

Changes:

  • src/code/list.lisp
    ... ... @@ -749,6 +749,7 @@
    749 749
     (defparameter *min-list-length-for-hashtable*
    
    750 750
       15)
    
    751 751
     
    
    752
    +(declaim (start-block list-to-hashtable union intersection set-difference))
    
    752 753
     ;; Convert a list to a hashtable.  The hashtable does not handle
    
    753 754
     ;; duplicated values in the list.  Returns the hashtable.
    
    754 755
     (defun list-to-hashtable (list key test test-not)
    
    ... ... @@ -802,6 +803,57 @@
    802 803
     	       (push item res)))))
    
    803 804
         res))
    
    804 805
     
    
    806
    +
    
    807
    +(defun intersection (list1 list2 &key key
    
    808
    +			   (test #'eql testp) (test-not nil notp))
    
    809
    +  "Returns the intersection of list1 and list2."
    
    810
    +  (declare (inline member))
    
    811
    +  (if (and testp notp)
    
    812
    +      (error "Test and test-not both supplied."))
    
    813
    +  (let ((hashtable 
    
    814
    +	  (list-to-hashtable list2 key test test-not)))
    
    815
    +    (cond (hashtable
    
    816
    +	   (let ((res nil))
    
    817
    +	     (dolist (item list1)
    
    818
    +	       (when (nth-value 1 (gethash (apply-key key item) hashtable))
    
    819
    +		 (push item res)))
    
    820
    +	     res))
    
    821
    +	  ((null hashtable)
    
    822
    +	   (let ((res nil))
    
    823
    +	     (dolist (elt list1)
    
    824
    +	       (if (with-set-keys (member (apply-key key elt) list2))
    
    825
    +		   (push elt res)))
    
    826
    +	     res)))))
    
    827
    +
    
    828
    +(defun set-difference (list1 list2 &key key (test #'eql testp) (test-not nil notp))
    
    829
    +  "Returns the elements of list1 which are not in list2."
    
    830
    +  (declare (inline member))
    
    831
    +  (if (and testp notp)
    
    832
    +      (error "Test and test-not both supplied."))
    
    833
    +  ;; Quick exit
    
    834
    +  (when (null list2)
    
    835
    +    (return-from set-difference list1))
    
    836
    +
    
    837
    +  (let ((hashtable 
    
    838
    +	  (list-to-hashtable list2 key test test-not)))
    
    839
    +    (cond (hashtable
    
    840
    +	   ;; list2 was placed in hash table.
    
    841
    +	   (let ((res nil))
    
    842
    +	     (dolist (item list1)
    
    843
    +	       (unless (nth-value 1 (gethash (apply-key key item) hashtable))
    
    844
    +		 (push item res)))
    
    845
    +	     res))
    
    846
    +	  ((null hashtable)
    
    847
    +	   ;; Default implementation because we didn't create the hash
    
    848
    +	   ;; table.
    
    849
    +           (let ((res nil))
    
    850
    +	     (dolist (item list1)
    
    851
    +	       (if (not (with-set-keys (member (apply-key key item) list2)))
    
    852
    +                   (push item res)))
    
    853
    +	     res)))))
    
    854
    +
    
    855
    +(declaim (end-block))
    
    856
    +
    
    805 857
     ;;; Destination and source are setf-able and many-evaluable.  Sets the source
    
    806 858
     ;;; to the cdr, and "conses" the 1st elt of source to destination.
    
    807 859
     ;;;
    
    ... ... @@ -834,28 +886,6 @@
    834 886
              (process (with-set-keys (member (apply-key key (car list1)) list2)))))
    
    835 887
           res)))
    
    836 888
       
    
    837
    -
    
    838
    -(defun intersection (list1 list2 &key key
    
    839
    -			   (test #'eql testp) (test-not nil notp))
    
    840
    -  "Returns the intersection of list1 and list2."
    
    841
    -  (declare (inline member))
    
    842
    -  (if (and testp notp)
    
    843
    -      (error "Test and test-not both supplied."))
    
    844
    -  (let ((hashtable 
    
    845
    -	  (list-to-hashtable list2 key test test-not)))
    
    846
    -    (cond (hashtable
    
    847
    -	   (let ((res nil))
    
    848
    -	     (dolist (item list1)
    
    849
    -	       (when (nth-value 1 (gethash (apply-key key item) hashtable))
    
    850
    -		 (push item res)))
    
    851
    -	     res))
    
    852
    -	  ((null hashtable)
    
    853
    -	   (let ((res nil))
    
    854
    -	     (dolist (elt list1)
    
    855
    -	       (if (with-set-keys (member (apply-key key elt) list2))
    
    856
    -		   (push elt res)))
    
    857
    -	     res)))))
    
    858
    -
    
    859 889
     (defun nintersection (list1 list2 &key key
    
    860 890
     			    (test #'eql testp) (test-not nil notp))
    
    861 891
       "Destructively returns the intersection of list1 and list2."
    
    ... ... @@ -882,33 +912,6 @@
    882 912
     	    (setq list1 (Cdr list1))))
    
    883 913
           res)))
    
    884 914
     
    
    885
    -(defun set-difference (list1 list2 &key key (test #'eql testp) (test-not nil notp))
    
    886
    -  "Returns the elements of list1 which are not in list2."
    
    887
    -  (declare (inline member))
    
    888
    -  (if (and testp notp)
    
    889
    -      (error "Test and test-not both supplied."))
    
    890
    -  ;; Quick exit
    
    891
    -  (when (null list2)
    
    892
    -    (return-from set-difference list1))
    
    893
    -
    
    894
    -  (let ((hashtable 
    
    895
    -	  (list-to-hashtable list2 key test test-not)))
    
    896
    -    (cond (hashtable
    
    897
    -	   ;; list2 was placed in hash table.
    
    898
    -	   (let ((res nil))
    
    899
    -	     (dolist (item list1)
    
    900
    -	       (unless (nth-value 1 (gethash (apply-key key item) hashtable))
    
    901
    -		 (push item res)))
    
    902
    -	     res))
    
    903
    -	  ((null hashtable)
    
    904
    -	   ;; Default implementation because we didn't create the hash
    
    905
    -	   ;; table.
    
    906
    -           (let ((res nil))
    
    907
    -	     (dolist (item list1)
    
    908
    -	       (if (not (with-set-keys (member (apply-key key item) list2)))
    
    909
    -                   (push item res)))
    
    910
    -	     res)))))
    
    911
    -
    
    912 915
     (defun nset-difference (list1 list2 &key key
    
    913 916
     			      (test #'eql testp) (test-not nil notp))
    
    914 917
       "Destructively returns the elements of list1 which are not in list2."
    
    ... ... @@ -935,7 +938,6 @@
    935 938
     	    (setq list1 (cdr list1))))
    
    936 939
           res)))
    
    937 940
     
    
    938
    -
    
    939 941
     (defun set-exclusive-or (list1 list2 &key key
    
    940 942
                              (test #'eql testp) (test-not nil notp))
    
    941 943
       "Return new list of elements appearing exactly once in LIST1 and LIST2."
    

  • src/i18n/locale/cmucl.pot
    ... ... @@ -3216,19 +3216,19 @@ msgid "Test and test-not both supplied."
    3216 3216
     msgstr ""
    
    3217 3217
     
    
    3218 3218
     #: src/code/list.lisp
    
    3219
    -msgid "Destructively returns the union list1 and list2."
    
    3219
    +msgid "Returns the intersection of list1 and list2."
    
    3220 3220
     msgstr ""
    
    3221 3221
     
    
    3222 3222
     #: src/code/list.lisp
    
    3223
    -msgid "Returns the intersection of list1 and list2."
    
    3223
    +msgid "Returns the elements of list1 which are not in list2."
    
    3224 3224
     msgstr ""
    
    3225 3225
     
    
    3226 3226
     #: src/code/list.lisp
    
    3227
    -msgid "Destructively returns the intersection of list1 and list2."
    
    3227
    +msgid "Destructively returns the union list1 and list2."
    
    3228 3228
     msgstr ""
    
    3229 3229
     
    
    3230 3230
     #: src/code/list.lisp
    
    3231
    -msgid "Returns the elements of list1 which are not in list2."
    
    3231
    +msgid "Destructively returns the intersection of list1 and list2."
    
    3232 3232
     msgstr ""
    
    3233 3233
     
    
    3234 3234
     #: src/code/list.lisp