2009-10-02 6 views

Répondre

5
user=> (use 'clojure.set) 
nil 
user=> (difference (set [1 2 3 4 5]) (set [2 3 5])) 
#{1 4} 

Référence:

+0

Y at-il un problème avec cette solution? –

+2

Un vecteur n'est pas un ensemble. L'ordre du vecteur n'est pas conservé lorsque vous le convertissez en ensemble. Si je comprends bien la question, (différence (set [9 2 3 4 5]) (set [2 3 5])) renvoie # {4 9} quand il devrait retourner [9 4] et (différence (set [1 1 2 3 4 5]) (set [2 3 5])) devrait retourner [1 1 4] et pas # {1 4} S'il voulait définir la sémantique, il aurait probablement utilisé un ensemble pour commencer avec. – Jonas

+0

Merci, Jonas. Tu as probablement raison de dire qu'il ne veut pas de sémantique. –

17

Essayez ceci:

(let [a [1 2 3 4 5] 
     b [2 3 5]] 
    (remove (set b) a)) 

qui renvoie (1 4). Soit dit en passant, la fonction remove prend un prédicat et une collection, et renvoie une séquence d'éléments qui ne satisfont pas le prédicat (un ensemble, dans cet exemple).

+1

... qui est O (n + m) – Thumbnail

+0

Comment '(set)' fonctionne-t-il ici en tant que prédicat pour 'remove'? Quelqu'un peut-il l'expliquer? Vous n'avez pas besoin du prédicat pour renvoyer false pour certains éléments de coll? – amirteymuri

+0

Un ensemble est aussi une fonction qui retournera la valeur qui lui est donnée si cette valeur est en elle-même, ou nil si ce n'est pas le cas. Si vous utilisez cette fonction en tant que prédicat, la valeur renvoyée devient true ou nil retournée devient false. C'est parce que dans Clojure nil est «falsey». –

1

Vous pouvez faire vous-même avec quelque chose comme:

(def a [2 3 5]) 
(def b [1 2 3 4 5]) 

(defn seq-contains? 
    [coll target] (some #(= target %) coll)) 

(filter #(not (seq-contains? a %)) b) 
; (3 4 5) 

Une version basée sur la bibliothèque reducers pourrait être:

(require '[clojure.core.reducers :as r]) 

(defn seq-contains? 
[coll target] 
    (some #(= target %) coll)) 

(defn my-remove 
"remove values from seq b that are present in seq a" 
[a b] 
(into [] (r/filter #(not (seq-contains? b %)) a))) 

(my-remove [1 2 3 4 5] [2 3 5]) 
; [1 4] 

EDITAjouté seq-contient? code

+2

Salut Nicolas, il se peut que je manque un point mais AFAIK contient? ne vérifie pas vraiment "contenu" mais vérifie plutôt l'index, consultez cet exemple; (contient? [7 2 3 4 5 6] 6) ;; false, il n'y a pas d'élément à l'index 6, bien qu'il y ait un élément 6. –

+0

Merci pour le pointeur. J'ai complètement oublié. Ajout du code pour un seq-contains? fonction. –

0

Voici ma prise sans utiliser de jeux;

(defn my-diff-func [X Y] 
    (reduce #(remove (fn [x] (= x %2)) %1) X Y)) 
Questions connexes