J'ai besoin de filtrer un vecteur donné de sorte que la sortie ne contienne que les éléments qui ne sont pas un doublon d'un voisin immédiat.
Example : I/P -> [1 1 3 2 2 4 5 5] O/P -> [3 4]
7 Réponses :
Il s'agit à peu près d'une solution de force brute, donc j'espère que nous verrons des réponses plus satisfaisantes, mais pour lancer le bal ...
(defn lonely? "Return the ith element of v if it doesn't have a matching neighbor" [i v] (when (cond (zero? i) (not= (v 0) (v 1)) (= i (- (count v) 1)) (not= (v i) (v (- i 1))) :else (and (not= (v i) (v (- i 1))) (not= (v i) (v (+ i 1))))) (v i))) > (def v [1 1 3 2 2 4 5 5]) > (keep #(lonely? % v) (range (count v))) (3 4)
(def data-3 [1 1 3 2 2 2 4 5 5 2 5 5]) ;[3 4 2]
(defn isolated [coll] (->> coll (partition-by identity) (remove next) (map first)))
Non. C'est assez explicite et les fonctions utilisées sont faciles à rechercher. Si Stack Overflow ne veut pas de réponses comme celle-ci, ils sont invités à la supprimer.
ou aplatir
au lieu de (map first)
@ fl00r Non, ce serait tout à fait faux. Essayez-le avec une entrée de [[1 2] [1 2]]
.
@amalloy, mais (remove next)
a déjà supprimé tous les seqs non simples, n'est-ce pas?
@ fl00r Oui, nous avons une liste de listes de singleton. Cependant, l'élément dans cette liste de singleton peut lui-même être une liste, que vous ne devriez pas aplatir. Mon entrée d'échantillon était erronée, cependant: il ne devrait pas y avoir de doublons. (partition par identité [[1 2]])
, par exemple, donne (([1 2]))
. remove next
ne le change pas, mais alors le résultat que nous voulons est ([1 2])
(c'est-à-dire, l'entrée inchangée). map first
donne cela, mais utiliser à la place flatten
donnerait (1 2)
, un aplatissement trop zélé.
Une autre façon de faire ceci:
(defn remove-consecutive-duplicates [inp] (let [intm (into [] (partition-by identity inp))] (reduce (fn [acc n] (if (= 1 (count n)) (conj acc n) acc )) [] intm)))
Notez que la déduplication ne donne pas le résultat souhaité.
déduplication
, pas dudupe
?
C'est exactement la même logique que la réponse de @ amalloy, mais elle utilise des transducteurs
au lieu de la macro de filetage ( - >>
).
(defn isolate [coll] (transduce (comp (partition-by identity) (remove next) (map first)) conj coll))
En le construisant plus ou moins à partir de zéro, vous pouvez obtenir une déstructuration pour faire une grande partie du travail:
(defn no-dupes [coll] (when-let [[x & [y & ys :as xs]] (seq coll)] (if xs (if (= x y) (recur (drop-while #(= x %) ys)) (lazy-seq (cons x (no-dupes xs)))) (list x))))
Cela dit, j'ai fait deux erreurs dans ces quelques lignes, alors que La réponse d'Alan Malloy est parfaitement correcte.
Est-ce que c'est plus rapide que la la version soignée du transducteur de @ dpassen ?
Oui. C'est environ trois fois plus rapide: environ 500 nano secondes contre environ 1,5 micro seconde pour l'exemple court, selon Criterium.
En utilisant des transducteurs comme la solution de @ amitr, mais à mon humble avis, un peu plus propre:
(def isolate (comp (partition-by identity) (remove next) cat))
Il peut ensuite être utilisé avec séquence
, dans code >, quelle que soit la fonction d'acceptation du transducteur souhaitée.
Quelle devrait être la sortie pour
[1 1 3 2 2 4 5 5 2 5 5]
? (Le dernier2
est-il supprimé parce qu'il y avait un2
répété plus tôt dans la séquence? Ou est-il conservé pour ne pas avoir un autre2
comme voisin ?)La sortie doit être [3 4 2]