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 dernier2est-il supprimé parce qu'il y avait un2répété plus tôt dans la séquence? Ou est-il conservé pour ne pas avoir un autre2comme voisin ?)La sortie doit être [3 4 2]