2011-12-05 12 views
8

voglio mettere a confronto due vettori e scoprire se gli oggetti che hanno sono la stessa, non importa l'ordine gli oggetti sono in.Confronta due vettori in clojure non importa l'ordine delle voci

Quindi ..

in questo momento in clojure:

(= [1 2 3] [3 2 1]) ;=> false 

voglio:

(other_fun [1 2 3] [3 2 1]) ;=> true 

(other_fun [1 2 3 4] [3 2 1]) ;=> false 

non riuscivo a trovare un containsA ll come in java

risposta

12

Se non si cura di duplicati, è possibile creare set di entrambi i vettori e confrontare questi:

(= (set [1 2 3]) (set [3 2 1])) ;=> true 

In funzione :

(defn set= [& vectors] (apply = (map set vectors))) 
4

creare set da loro:

user=> (= (set [1 2 3]) (set [3 2 1])) 
true 


user=> (defn other_func [col1 col2] 
     (= (set col1) (set col2))) 
#'user/other_func 
user=> (other_func [1 2 3] [3 2 1]) 
true 
8

Se non si cura di duplicati, altre risposte perfettamente applicabili ed efficienti. Ma se interessa duplicati, probabilmente il modo più semplice per confrontare due vettori è ordinamento e il confronto:

user=> (= (sort [3 5 2 2]) (sort [2 2 5 3])) 
true 
user=> (= (sort [3 5 2 2]) (sort [2 5 3])) 
false 
21

Se si preoccupano su duplicati, è possibile confrontare le loro mappe di frequenza. Queste sono mappe con ogni elemento della raccolta come una chiave e il numero di occorrenze come valore. Li crei usando la funzione standard frequencies, come negli esempi forniti.

ordine differente, lo stesso numero di duplicati:

(= (frequencies [1 1 2 3 4])(frequencies [4 1 1 2 3]))

viene valutata true.

ordine differente, diverso numero di duplicati:

(= (frequencies [1 1 2 3 4])(frequencies [4 1 2 3]))

viene valutata false.

Quindi, è possibile scrivere una funzione:

(defn other_fun [& colls] 
    (apply = (map frequencies colls))) 
2

Sei sulla JVM già, quindi se volete containsAll, poi basta usare containsAll, giusto?

+1

'containsAll' determina se una raccolta è un sottoinsieme dell'altra raccolta. Non determina l'uguaglianza dell'insieme. – Confusion

+0

@Confusion Puoi usare 'a.containsAll (b) && b.containsAll (a)'. – bfontaine

1
(defn other_fun 
    "checkes the presence of the elements of vec1 in vec2 and vice versa" 
    [vec1 vec2] 
    (if (or (some nil? 
      (for [a vec1 b [vec2]] (some #(= % a) b))) 
     (some nil? 
      (for [a vec2 b [vec1]] (some #(= % a) b)))) 
    false 
    true)) 

(other_fun [1 2 3] [3 2 1]) ;=> true 

(other_fun [1 2 3 4] [3 2 1]) ;=> false 
+0

È possibile semplificare '(se x false true)' come '(not x)'. – bfontaine