In Clojure, you can do this in much the same way - first call distinct to get unique values, and then use count to count the results:
(def vectors (list [ 100 2000 ] [ 100 2000 ] [ 101 2001 ] [ 100 2002 ])) (defn count-unique [coll] (count (distinct coll))) (def result [(count-unique (map first vectors)) (count-unique (map second vectors))])
Please note that here you first get a list of the first and second elements of the vectors (draw the first / second vectors), and then operate separately and, thus, repeating the collection twice. If performance matters, you can do the same with iteration (see loop shape or recursion tail) and sets, as in Java. You can also use transients to further improve performance. Although for beginners, like you, I would recommend the first way with distinct .
UPD. Here's the version with the loop:
(defn count-unique-vec [coll] (loop [coll coll, e1 (transient
As you can see, there is no need for atoms or anything like that. First, you pass the state of each subsequent iteration (callback). Secondly, you use transients to use temporary mutable collections (read more about transients in more detail) and, therefore, avoid creating a new object each time.
UPD2. Here is the version with reduce for the extended question (with price):
(defn count-with-price "Takes input of form ([customer invoice price] [customer invoice price] ...) and produces vector of 3 elements, where 1st and 2nd are counts of unique customers and invoices and 3rd is total sum of all prices" [coll] (let [[custs invs total] (reduce (fn [[custs invs total] [cust inv price]] [(conj! custs cust) (conj! invs inv) (+ total price)]) [(transient #{}) (transient #{}) 0] coll)] [(count (persistent! custs)) (count (persistent! invs)) total]))
Here we conduct the intermediate results in the [custs invs total] vector, unpack, process and return them back to the vector every time. As you can see, implementing such nontrivial logic with reduce more complicated (both for writing and reading) and requires even more code (in the loop ed version it is enough to add one more parameter for the price for args cycles). Therefore, I agree with @ammaloy that for simpler cases, reduce better, but more complex things require lower-level constructs such as a loop/recur .