8

Emacs Lispで2つのセットの差を計算するには? セットはリストでなければなりません。プログラムは非常に単純で短くなければなりません。さもないと理解できません。私は初心者です。

どうも

4

5 に答える 5

10

set-differenceCommon Lisp 拡張機能には次の関数があります。

elisp> (require 'cl-lib)
cl-lib
elisp> (cl-set-difference '(1 2 3) '(2 3 4))
(1)
于 2012-06-07T21:52:11.257 に答える
6

多くのリスト データ変換を含む Elisp コードを記述するときは、dashライブラリを使用します。これは、リストを操作するための関数が多数あるためです。集合差は次のようにして行うことができます-difference:

(require 'dash)
(-difference '(1 2 3 4) '(3 4 5 6)) ;; => '(1 2)
于 2014-11-18T07:42:06.210 に答える
3

免責事項: これは eLisp で効率的な方法ではありません。効率的な方法は、ハッシュ関数を使用したハッシュテーブルを使用することですが、リストについて尋ねたので、次のとおりです。

(defun custom-set-difference (a b)
  (remove-if
     #'(lambda (x) (and (member x a) (member x b)))
     (append a b)))

(custom-set-difference '(1 2 3 4 5) '(2 4 6))

(1 3 5 6)

(defun another-set-difference (a b)
  (if (null a) b
    (let (removed)
      (labels ((find-and-remove
                (c)
                (cond
                 ((null c) nil)
                 ((equal (car c) (car a))
                  (setq removed t) (cdr c))
                 (t (cons (car c) (find-and-remove (cdr c)))))))
        (setf b (find-and-remove b))
        (if removed
            (another-set-difference (cdr a) b)
          (cons (car a) (another-set-difference (cdr a) b)))))))

(another-set-difference '(1 2 3 4 5) '(2 4 6))

(1 3 5 6)

2 番目の方法は、後続のチェックを行うときに要素を削除するため、わずかに効率的ですが、最初の方法は短くて簡単です。

また、リストは自然に繰り返しが許されるため、セットの適切な表現ではないことに注意してください。その目的にはハッシュマップの方が適しています。

于 2012-06-07T23:06:43.000 に答える
2

これは、理解しやすいはずの簡単で短い定義です。これは、Emacs の Common Lisp ライブラリの関数と本質的に同じset-differenceですが、TEST 引数の処理はありません。

(defun set-diff (list1 list2 &optional key)
  "Combine LIST1 and LIST2 using a set-difference operation.
Optional arg KEY is a function used to extract the part of each list
item to compare.

The result list contains all items that appear in LIST1 but not LIST2.
This is non-destructive; it makes a copy of the data if necessary, to
avoid corrupting the original LIST1 and LIST2."
  (if (or (null list1)  (null list2))
      list1
    (let ((keyed-list2  (and key  (mapcar key list2)))
          (result       ()))
      (while list1
        (unless (if key
                    (member (funcall key (car list1)) keyed-list2)
                  (member (car list1) list2))
          (setq result  (cons (car list1) result)))
        (setq list1  (cdr list1)))
      result)))
于 2013-10-27T22:45:13.520 に答える