August 27, 2018

Just Juxt #13: Find Distinct Items (4clojure #56)

Calvin

Write a function which removes the duplicates from a sequence. Order of the items must be maintained.

And not so fast... we're not allowed to use distinct! Here we take the concept of restricted functions to the next level: Solution must use juxt!

(ns live.test
  (:require [cljs.test :refer-macros [deftest is testing run-tests]]))
  
(defn deduper [s]
  )

(deftest deduper-test
  (is (= (deduper [1 2 1 3 1 2 4]) [1 2 3 4]))
  (is (= (deduper [:a :a :b :b :c :c]) [:a :b :c]))
  (is (= (deduper '([2 4] [1 2] [1 3] [1 3])) '([2 4] [1 2] [1 3])))
  (is (= (deduper (range 50)) (range 50))))
  
(run-tests)

Answer:

(defn deduper [coll]
  (->> coll
       (map-indexed vector)
       (group-by second)
       (map (juxt first (comp ffirst second)))
       (sort-by second)
       (map first)))
       
(run-tests)

Breakdown:

(->> [1 2 1 3 1 2 4]
       (map-indexed vector)
       (group-by second)
       (map (juxt first (comp ffirst second)))
       (sort-by second)
       (map first))
(map-indexed vector [1 2 1 3 1 2 4])
(group-by second '([0 1] [1 2] [2 1] [3 3] [4 1] [5 2] [6 4]))

Some magic right here:

(map (juxt first (comp ffirst second)) {1 [[0 1] [2 1] [4 1]], 2 [[1 2] [5 2]], 3 [[3 3]], 4 [[6 4]]})

Then we sort them and take the first digits. This particular collection happens to be already sorted:

(map first '([1 0] [2 1] [3 3] [4 6]))
Tags: coding exercises KLIPSE 4clojure Cryogen juxt