2017-10-21 1 views
3

Ich versuche, Duplikate in einem Vektor mit leeren Zeichenfolgen zu ersetzen. Die einzigen Funktionen, die ich finden kann, sind jedoch, Duplikate zu entfernen, sie nicht zu ersetzen. Wie kann ichErsetzen Duplikate in Clojure Vektor

["Oct 2016" "Oct 2016" "Nov 2016" "Nov 2016" "Nov 2016" "Nov 2016"]

und Ausgang:

["Oct 2016" "" "Nov 2016" "" "" ""]

Alles, was ich zurückkehren ["Oct 2016" "Nov 2016"] finden kann ich zur Zeit die gewünschte Ausgabe zu erreichen, indem eine verschachtelte doseq tun, aber es scheint ineffizient . Gibt es einen besseren Weg, dies zu erreichen? Danke!

Antwort

5

Hier ist eine Strategie für eine Lösung.

  1. loop über die Elemente des Vektors.
  2. Pflegen Sie eine set der besuchten Artikel. Es kann verwendet werden, um auf Eindeutigkeit zu prüfen.
  3. Für jeden Artikel: Wenn der Satz den aktuellen Artikel enthält, fügen Sie "" in den Ergebnisvektor ein.
  4. Wenn das aktuelle Element eindeutig ist, fügen Sie es in den Ergebnisvektor und das Set ein.
  5. Geben Sie den Ergebnisvektor zurück, wenn alle Elemente besucht wurden.
  6. Optional: Verwenden Sie einen transient Ergebnisvektor für eine bessere Leistung.

Code:

(defn duplicate->empty [xs] 
    (loop [xs  (seq xs) 
     result [] 
     found #{}] 
     (if-let [[x & xs] (seq xs)] 
      (if (contains? found x) 
      (recur xs (conj result "") found) 
      (recur xs (conj result x) (conj found x))) 
      result))) 

es aufrufen:

(duplicate->empty ["Oct 2016" "Oct 2016" "Nov 2016" "Nov 2016" "Nov 2016" "Nov 2016"]) 
=> ["Oct 2016" "" "Nov 2016" "" "" ""] 
+0

während der ersten Erstellung des Vektors Beheben des Problems Ended, aber dies auch nicht funktioniert, als Lösung markiert. – Zaden

0

Sie iterate verwenden:

(def months ["Oct 2016" "Oct 2016" "Nov 2016" "Nov 2016" "Nov 2016" "Nov 2016"]) 

(defn step [[[head & tail] dups res]] 
    [tail 
    (conj dups head) 
    (conj res (if (dups head) 
       "" 
       head))]) 

(defn empty-dups [xs] 
    (->> (iterate step [xs #{} []]) 
     (drop-while (fn [[[head] _ _]] head)) 
     (map #(nth % 2)) 
     first)) 

(empty-dups months) 
;; => ["Oct 2016" "" "Nov 2016" "" "" ""] 
1
(defn eliminate-duplicates [v] 
     (let [result (transient (vec (repeat (count v) ""))) 
       index-of-first-occurences (apply merge-with #(first %&) (map-indexed (fn [x y] {y x}) v))] 
      (doall (for [[s pos] index-of-first-occurences] 
         (assoc! result pos s))) 
      (persistent! result))) 
2

Transducer-Version nur für comp Leteness.

(defn empty-duplicates 
    ([] 
    (fn [rf] 
    (let [seen (volatile! #{})] 
     (fn 
     ([] (rf)) 
     ([res] (rf res)) 
     ([res x] 
      (if (contains? @seen x) 
      (rf res "") 
      (do (vswap! seen conj x) 
       (rf res x)))))))) 
    ([coll] 
    (sequence (empty-duplicates) coll))) 

(comment 

    (def months ["Oct 2016" "Oct 2016" "Nov 2016" "Nov 2016" "Nov 2016" "Nov 2016"]) 

    (into [] (empty-duplicates) months) ;=> ["Oct 2016" "" "Nov 2016" "" "" ""] 

) 
1

im Grunde das gleiche wie oben, aber mit faulen Sequenz Generation:

(defn rdups 
    ([items] (rdups #{} items)) 
    ([found [x & xs :as items]] 
    (when (seq items) 
    (if (contains? found x) 
     (lazy-seq (cons "" (rdups found xs))) 
     (lazy-seq (cons x (rdups (conj found x) xs))))))) 

user> (rdups ["Oct 2016" "Oct 2016" "Nov 2016" "Nov 2016" "Nov 2016" "Nov 2016"]) 
;;=> ("Oct 2016" "" "Nov 2016" "" "" "") 
+0

verwendet Lazy-Seq (wie akzeptiert ans) PLUS lässt die Schleife fallen. sieht für mich am saubersten aus. –

Verwandte Themen