2
votes

Comment comparer les valeurs d'éléments consécutifs dans un vecteur pour le filtrage?

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]


2 commentaires

Quelle devrait être la sortie pour [1 1 3 2 2 4 5 5 2 5 5] ? (Le dernier 2 est-il supprimé parce qu'il y avait un 2 répété plus tôt dans la séquence? Ou est-il conservé pour ne pas avoir un autre 2 comme voisin ?)


La sortie doit être [3 4 2]


7 Réponses :


2
votes

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)


0 commentaires

2
votes
(def data-3 [1 1 3 2 2 2 4 5 5 2 5 5])
;[3 4 2]

0 commentaires

8
votes
(defn isolated [coll]
  (->> coll
       (partition-by identity)
       (remove next)
       (map first)))

5 commentaires

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é.



0
votes

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é.


1 commentaires

déduplication , pas dudupe ?



7
votes

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))


0 commentaires

1
votes

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.


0 commentaires

4
votes

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.


0 commentaires