{{ message }}

Instantly share code, notes, and snippets.

# ericnormand/00 Uniques.md

Last active Jun 26, 2020

unique values

Let's keep it easy this week as we get back into it.

Write a function called `uniques` that takes a sequence of values. That sequence is going to have zero or more unique values. The rest will repeat at least once. Your job is to return the unique values in the same order as they appear in the argument sequence.

Examples

```(uniques [1 2 3 4 5 6 1 2 3 5 6]) ;=> (4)
(uniques [:a :b :c :c]) ;=> (:a :b)
(uniques [1 2 3 1 2 3]) ;=> ()```

Thanks to this site for the challenge idea where it is considered Medium level in Python.

Email submissions to eric@purelyfunctional.tv before June 21, 2020. You can discuss the submissions in the comments below.

 (ns tst.demo.core (:use tupelo.core tupelo.test)) (defn uniques [vals] (let [freqs (frequencies vals) result (vec (keys (t/submap-by-vals freqs #{1} :missing-ok)))] result)) (dotest (is= (uniques [1 2 3 4 5 6 1 2 3 5 6]) ) (is= (uniques [:a :b :c :c]) [:a :b]) (is= (uniques [1 2 3 1 2 3]) []))
 (defn uniques [xs] (->> (get (group-by second (frequencies xs)) 1) (map first)))
 (ns uniques) (require '[clojure.test :as test]) (defn uniques [coll] (filter (fn [elt-e] (= 1 (count (filter (fn [elt-i] (= elt-i elt-e)) coll)))) (reverse (set coll)))) (test/deftest uniques-test (test/is (= '(4) (uniques [1 2 3 4 5 6 1 2 3 5 6]))) (test/is (= '(:a :b) (uniques [:a :b :c :c]))) (test/is (= '() (uniques [1 2 3 1 2 3])))) (test/run-tests 'uniques)
 (defn uniques [xs] (->> (group-by identity xs) (vals) (filter (comp (partial = 1) (partial count))) (mapcat identity)))
 (ns purelyfun.382.core) (defn uniques [values] (map first (filter #(= (count %) 1) (vals (group-by identity values))))) (ns purelyfun.382.test (:require [clojure.test :refer :all] [purelyfun.382.core :refer :all])) (deftest test-unique (is (= (uniques [1 2 3 4 5 6 1 2 3 5 6]) '(4))) (is (= (uniques [:a :b :c :c]) '(:a :b))) (is (= (uniques [1 2 3 1 2 3]) '())) ) (comment (clojure.test/run-tests 'purelyfun.382.test) (defn rt [] (let [tns 'purelyfun.382.test] (use tns :reload-all) (clojure.test/test-ns tns)) ) )
 (defn single-in-coll? [n coll] (= 1 (count (filter #(= % n) coll)))) (defn uniques [coll] (filter #(single-in-coll? % coll) coll))
 (defn ordered-frequencies [seq] (reduce #(assoc %1 %2 (inc (get %1 %2 0))) (array-map) seq)) (defn uniques [seq] (map first (filter #((partial = 1) (second %)) (ordered-frequencies seq))))
 (ns functional-tv-puzzles.-2020.uniques-382) ;; Hand-rolled without frequencies. Two-pass, including ordering (defn ordering [xs] (->> xs (into {} (map-indexed #(vector %2 %1))))) (defn uniques [xs] (let [o (ordering xs)] (loop [seen #{} kept (sorted-set-by #(< (o %) (o %2))) [x & more :as coll] xs] (cond (empty? coll) (apply list kept) (seen x) (recur seen (disj kept x) more) :else (recur (conj seen x) (conj kept x) more)))))
 (defn uniques [coll] (sort (vec (set coll))) )
 (defn uniques "Returns a seq containing the values that appear exactly once in `s`. The order in which the values appear in `s` is preserved." [s] (->> s (filter #(= 1 ((frequencies s) %))))) ;; Note to self: when ordering is involved, test with at ;; least 33 elements. Data transformation pipelines often ;; include tranforming to maps (e.g. frequencies, zipmap). ;; Coincidentally, for small maps, Clojure seems to preserve ;; order up to and including 8 elements; ClojureScript does ;; this up to and including 32 elements. (assert (= (uniques (concat (range 33) [1 3 5])) [0 2 4 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32]))
 (defn uniques [xs] (filter (comp #(= 1 %) (frequencies xs)) xs))
 (defn uniques [l] (for [e l :when (= 1 (count (filter #{e} l)))] e))
 (defn uniques [coll] (->> coll (group-by identity) (filter (fn [[_ [_ & rest]]] (empty? rest))) (map first)))
 (defn uniques [coll] (let [freqs (frequencies coll)] (filter #(= 1 (get freqs %)) coll)))
 (defn uniques [xs] (let [unique-items (->> xs frequencies (filter #(= 1 (val %))) keys set)] (if (some nil? unique-items) (filter #(or (nil? %) (unique-items %)) xs ) (filter unique-items xs )))) (deftest uniques-test (testing "uniques" (is (= '(:a :b) (uniques [:a :b :c :c]))) (is (= '(4) (uniques [1 2 3 4 5 6 1 2 3 5 6]))) (is (= '() (uniques [1 2 3 1 2 3]))) (is (= '(nil 1) (uniques [nil 2 3 1 2 3]))) (is (= '() (uniques [nil nil ])))))
 (defn uniques [xs] (let [counts (frequencies xs) dups (->> (filter (fn [[x cnt]] (> cnt 1)) counts) (map first) set)] (remove #(contains? dups %) xs)))
 (defn uniques "Given a sequence of values return, in the same order in which they appear, those among them that are unique e.g. [1 2 1 3] ==> [2 3]." [v] (let [same (group-by identity v)] (reduce (fn [res k] (if (= 1 (count (get same k))) (conj res k) res)) [] v)))
 (defn uniques [xs] (let [freqs (frequencies xs)] (filter #(= 1 (freqs %)) xs)))
 (defn uniques [xs] (let [freq (frequencies xs)] (for [x xs :when (= 1 (get freq x))] x)))

### souenzzo commented Jun 15, 2020

 ```(defn uniques [coll] ;; To return if a element is unique, I need ;; to realize all collection. So `frequencies` ;; should do that in a optimal way (let [h (frequencies coll)] ;; I can return result lazily, once I have a "global index" (filter (comp #{1} h) coll)))```

### NPException commented Jun 15, 2020

 I just noticed that @souenzzo posted essentially same solution already, but here is mine anyway: ```(defn uniques [xs] (let [counts (frequencies xs)] (filter #(== 1 (counts %)) xs)))```

### KingCode commented Jun 15, 2020 • edited

 I am inspired by @souenzzo's `(comp #{1} ...)`. My solution is more convoluted by iterating on the frequencies instead of the coll. Two variants: ``````(defn ordering [xs] (->> xs (map-indexed #(vector %2 %)) (into {}))) (defn key-when [pred] (fn [[k v]] (when (pred v) k))) (defn uniques [xs] (->> xs frequencies (keep (key-when #{1})) (sort-by (ordering xs)))) (defn uniques-2 [xs] (let [o (ordering xs)] (->> xs frequencies seq flatten (apply sorted-map-by #(compare (o %) (o %2))) (keep (key-when #{1}))))) ``````

### burnall commented Jun 15, 2020

 It is a rare case when it is optimal to use `->` pipeline with collections. ``````(defn uniques [coll] (-> coll (frequencies) (#(fn [x] (= 1 (% x)))) (filter coll))) ``````

### duzunov commented Jun 15, 2020 • edited

 Here is my submission: ```(defn single-in-coll? [n coll] (= 1 (count (filter #(= % n) coll)))) (defn uniques [coll] (filter #(single-in-coll? % coll) coll))```

### zugnush commented Jun 16, 2020 • edited

 I think from the spec that maybe a unique nil should be reported ```(defn uniques [xs] (let [unique-items (->> xs frequencies (filter #(= 1 (val %))) keys set)] (if (some nil? unique-items) (filter #(or (nil? %) (unique-items %)) xs ) (filter unique-items xs )))) (deftest uniques-test (testing "uniques" (is (= '(:a :b) (uniques [:a :b :c :c]))) (is (= '(4) (uniques [1 2 3 4 5 6 1 2 3 5 6]))) (is (= '() (uniques [1 2 3 1 2 3]))) (is (= '(nil 1) (uniques [nil 2 3 1 2 3]))) (is (= '() (uniques [nil nil ]))))) ```

### tychobrailleur commented Jun 17, 2020 • edited

 ```(defn uniques [v] (->> v (frequencies) (filter #(<= (second %) 1)) (map first)))```

### burnall commented Jun 18, 2020

 @tychobrailleur This condition "unique values in the same order as they appear in the argument sequence" is not fulfilled, unfortunately. It would be nice to use `into` for java.util.LinkedHashSet which keeps insertion order, but it does not work.