Does Clojure have a set that remembers insertion order? - clojure

Like Java's LinkedHashSet. So instead of this:
(-> #{} (conj 1 2 3 4 5) vec)
=> [1 4 3 2 5]
You get:
(-> ??? (conj 1 2 3 4 5) vec)
=> [1 2 3 4 5]

Not in the core library, but there's this one.
(use 'flatland.ordered.set)
(ordered-set 4 3 1 8 2)
=> #ordered/set (4 3 1 8 2)
(conj (ordered-set 9 10) 1 2 3)
=> #ordered/set (9 10 1 2 3)
(into (ordered-set) [7 6 1 5 6])
=> #ordered/set (7 6 1 5)

Related

Multiply nested pairs of list values in Clojure

What I am ultimately trying to do is multiply two vectors together and return a vector of the same size eg:
[6 7 8 9 10] * [0 1 3 1 0] => [0 7 24 9 0]
I was attempting to do something like:
(partition 2 (interleave [6 7 8 9 10] [0 1 3 1 0])) => ((6 0) (7 1) (8 3) (9 1) (10 0))
... then multiply each nested list value and use flatten to get:
(0 7 24 9 0)
but I cant figure out how I could multiply nested list values?
Map takes multiple sequences and a function to combine each member with the corresponding member of the other sequences.
user> (map * [6 7 8 9 10] [0 1 3 1 0])
(0 7 24 9 0)
user> (mapv * [6 7 8 9 10] [0 1 3 1 0])
[0 7 24 9 0]
in this case it calls * on the first number from each list, then on the second from each list and so on, building a seq of the output. If you would prefer the output in a vector mapv is convenient.

Clojure reverse-flattening lists. E.g. '(1 2 3 4 5 6) to '( (1 2) (3 4) (5 6)

Is there a core function or some idiomatic way to do a "reverse flattening" of a collection?
E.g. I would like the following:
(by-two '(1 2 3 4 5 6)) ; evals to '( (1 2) (3 4) (5 6) )
Of course the form in the above case would need an even number of elements or the function should do something sensible if presented with an odd-numbered collection. A generalized by-n function would be better of course. It's not clear to me whether there's any merit in trying to generalize the concept in depth as well or what's the best form to do so:
(by [2 2] '(1 2 3 4 5 6 7 8)) ; evals to '( ( (1 2) (3 4) ) ( (5 6) (7 8) ) )
(by [3 2 1 1 1] '(1 2 3 4 5 6)) ; evals to '(((((1 2 3) (4 5 6)))))
You can use reduce and partition :
(reduce #(partition %2 %1) '(1 2 3 4 5 6 7 8) [2 2])
There's partition:
(partition 2 [1 2 3 4 5])
> ((1 2) (3 4))
If you want to include the small tail, there's partition-all:
(partition-all 2 [1 2 3 4 5])
> ((1 2) (3 4) (5))
There is no such standard function I aware of. But partition is helpful:
(defn by [sizes coll]
(if sizes
(by (next sizes) (partition (first sizes) coll))
coll))

How to split a sequence into every 3 neighbor elements in clojure?

Given a sequence like:
[1 2 3 4 5 6]
How to split it into every 3 neighbor elements in clojure? Just like the following:
([1 2 3] [2 3 4] [3 4 5] [4 5 6])
Functions in clojure.core are preferred!
See partition:
user=> (partition 3 1 [1 2 3 4 5 6])
((1 2 3) (2 3 4) (3 4 5) (4 5 6))

Unflattening a sequence to sequences of repeating elements (clojure)

In Clojure, how do you partition a sequence to subsequences of repeating elements? E.g. :
[1 2 2 3 3 3 4 2 2 1 1 1]
to
[[1] [2 2] [3 3 3] [4] [2 2] [1 1 1]]
I've been playing around with some examples trying to understand clojure better, and was stuck on this one for some time.
user> (partition-by identity [1 2 2 3 3 3 4 2 2 1 1 1])
((1) (2 2) (3 3 3) (4) (2 2) (1 1 1))
user> (vec (map vec (partition-by identity [1 2 2 3 3 3 4 2 2 1 1 1])))
[[1] [2 2] [3 3 3] [4] [2 2] [1 1 1]]
(map (juxt count first)
(partition-by identity [1 1 1 3 2 2]))
((3 1) (1 3) (2 2))
Three ones, then one three, followed by two twos!

best way to repeatedly map values from a sequence into an arg list?

Sorry for the noob question, but is there an good way to destructure values from a sequence like this..
(somefunc [[a b c] [1 2 3 4 5 6 7 8 9]] (prn a b c))
..with the a b c being assigned values until the sequence exhausted and letting me call a function on the args? doseq requires a partition of the right size..
(doseq [[a b c] (partition 3 [1 2 3 4 5 6 7 8 9])] (prn a b c))
Output:
1 2 3
4 5 6
7 8 9
That does what I want, but it seems like there should be a way to do this in s straightforward way without having to specify the partition. I found a solution with loop/recur but it's a lot more code and clearly non-idiomatic. What's a good way to do this? Thanks!
(defn apply-to-three [f [a b c & xs]]
(f a b c)
(when xs
(recur f xs)))
user=> (apply-to-three prn [1 2 3 4 5 6 7 8 9])
1 2 3
4 5 6
7 8 9
nil
(defn some-func
[[a b c & rest :as all]]
(prn a b c)
(prn rest)
(prn all)
user> (some-func [1 2 3 4 5 6 7])
1 2 3
(4 5 6 7)
[1 2 3 4 5 6 7]
Read more about destructing: http://java.ociweb.com/mark/clojure/article.html#Destructuring
An alternate, lower-level solution using loop destructuring:
user=> (def coll [1 2 3 4 5 6 7 8 9 10])
#'user/coll
user=> (loop [[a b c & more] coll]
user=* (when a
user=* (prn a b c)
user=* (recur more)))
1 2 3
4 5 6
7 8 9
10 nil nil
nil
or use when c to exit after the last complete triplet.
Using map and partition:
(map prn (partition 3 [1 2 3 4 5 6 7 8 9]))
partition + map is all you need. Read about dorun, doseq and doall: http://onclojure.com/2009/03/04/dorun-doseq-doall/
user> (dorun (map #(apply prn %) (partition 3 [1 2 3 4 5 6 7 8 9])))
1 2 3
4 5 6
7 8 9
nil