destruct short lazy sequences to vector or map - clojure

Say I have a data structure like this:
((v v v) (v v v) (v v v) ...)
A lazy sequence of lazy sequences. The inner ones always count 3 arbitrary values. This structure is the result of calling partition on a vector.
No I need to convert this structure to the following:
([[v v] v] [[v v] v] [[v v] v] ...)
First question:
Which approach would be preferable here:
(map #(identity [(take 2 %) (last %)]) myseq)
or.
(map (fn [[a b c]] [[a b] c]) myseq)
or. something else?
Second question:
Would it be less efficient to map it to a data structure like this:
({:k1 [a b] :k2 c} .. )
Which would make sense for my project in a way. In other words: is the creation of and the access to a hashmap slower/faster compared to a vector.

I would probably use transducers for this
(into {}
(comp (partition-all 3)
(map (fn [[a b c]] [[a b] c])))
(range 10))
=> {[0 1] 2, [3 4] 5, [6 7] 8, [9 nil] nil}
In other words: is the creation of and the access to a hashmap slower/faster compared to a vector.
A vector doesn't (easily) allow access by value, only by key. So if you need to do lookups by [a b], then a hashmap is your best option.

I think your second solution is preferable and just fine :)
Personally I'd go with a for expression:
(for [[a b c] (partition-all 3 xs)]
{:k1 [a b]
:k2 c])
As for the efficiency of small maps vs small vectors; Clojure is good at both! I wouldn't even sweat it. Go with the most semantically meaningful choice. It is highly unlikely that going one way or the other will make any even remotely significant difference to your performance. Of course if you are really pressed, a microbenchmark using criterium will guide you. What will make a massive difference is how the data is used... as Daniel pointed out.

Related

Select element in collection satisfying max in Clojure

The following expression
(reduce (fn [[c x y] [s k d]] (if (< c s) [s k d] [c x y])) [0 0 0] colls)
Is for the element [e, x, y] in colls such that e is the maximum among all in the tuples in colls.
Is there already an idiomatic expression in Clojure for that? I guess that with macro, it should be possible to express it with brevity.
I feel that Python/numpy/panda has some good example.
You can use max-key:
(apply max-key first colls)

What is meant by destructuring in Clojure?

I'm a Java and learning clojure.
What is exactly destructuring in clojure?
I can see this blog saying:
The simplest example of destructuring is assigning the values of a
vector.
user=> (def point [5 7])
#'user/point
user=> (let [[x y] point]
(println "x:" x "y:" y))
x: 5 y: 7
what he meant by assigning the values of a vector? Whats the real use of it?
Thanks in advance
point is a variable that contains a vector of values. [x y] is a vector of variable names.
When you assign point to [x y], destructuring means that the variables each get assigned the corresponding element in the value.
This is just a simpler way of writing:
(let [x (nth point 0) y (nth point 1)]
(println "x:" x "y:" y))
See Clojure let binding forms for another way to use destructuring.
It means making a picture of the structure of some data with symbols
((fn [[d [s [_ _]]]]
(apply str (concat (take 2 (name d)) (butlast (name s)) (drop 7 (name d))) ))
'(describing (structure (of data))))
=> "destructuring"
((fn [[d e _ _ _ _ _ i n g _ _ _ _ _ s t r u c t u r e & etc]]
[d e s t r u c t u r i n g]) "describing the structure of data")
=> [\d \e \s \t \r \u \c \t \u \r \i \n \g]
Paste those ^ examples into a REPL & play around with them to see how it works.
The term "Destructuring" sounds heavier than it is.
It's like visually matching shapes to shapes. For example:
(def nums [1 2 3 4 5 6])
(let [[a b c & others] nums]
;; do something
)
Imagine the effect of the let binding as:
1 2 3 4 5 6
| | | ( )
v v v v
[a b c & others]
;; Now we can use a, b, c, others, and of course nums,
;; inside the let binding:
user=> (let [[a b c & others] nums]
(println a)
(println b)
(println c)
(println others)
(println nums))
1
2
3
(4 5 6)
[1 2 3 4 5 6]
The goal is to concisely name items of a collection, for use inside the scope of a let binding or function (i.e. within a "lexical scope").
Why "concise"? Well, without destructuring, the let binding would look like this:
(let [a (nth nums 0) ;; or (first nums)
b (nth nums 1) ;; or (second nums)
c (nth nums 2)
others (drop 3 nums)]
;; do something
)
This illustrates the basic idea. There are many details (ifs and buts, and dos and don'ts), and it's worth reading further, in depth. Here are a few resources that explain more, with examples:
My personal favourite: Jay Fields's post on Clojure Destructuring:
http://blog.jayfields.com/2010/07/clojure-destructuring.html
A gentle introduction to destructuring, from Braveclojure:
http://www.braveclojure.com/do-things/#3_3_3__Destructuring
its used to name components of a data structure, and get their values.
Say you want to have a "person" structure. In java, you would go all the way to create a class with constructors, getters and setters for the various fields, such as name, age, height etc.
In Clojure you could skip the "ceremony" and simply have a vector with 3 slots, first for name, than for age and last for height. Now you could simply name these "components" and get their values, like so:
(def person ["Fred" 30 180])
(let [[name age height] person]
(println name age height)) ;; will print: Fred 30 180
p.s - there are better ways to make a "person" in clojure (such as records etc), this is just an example to understand what destructuring does.
Destructuring is a convenience feature which allows local bindings (not variables!) to be created easily by taking apart complex data structures (seq-ables like vectors, or associatives like hash-maps), as it is described here.
Take the following example:
(let [v [1 2 3 4 5 6]
v_0 (first v)
v_1 (nth v 1)
v_rest (drop 2 v)
m {:a 1 :b 2}
m_a (get m :a)
m_b (get m :b)
m_default (get m :c "DEFAULT")]
(println v, v_0, v_1, v_rest, m, m_a, m_b, m_default))
Then the above code can be simplified using destructuring bindings like the following:
(let [[v_0 v_1 & v_rest :as v]
[1 2 3 4 5 6]
{m_a :a m_b :b m_default :c :or {m_default "DEFAULT"} :as m}
{:a 1 :b 2}]
(println v, v_0, v_1, v_rest, m, m_a, m_b, m_default))
Destructuring patterns can be used in let bindings and function parameters (fn, defn, letfn, etc.), and also in macros to return let bindings containing such destructuring patterns.
One important usage to note is with the if-letand when-let macros. The if statement is always evaluated on the whole form, even if the destructured bindings themselves evaluate to nil:
(if-let [{:keys [a b]}
{:c 1 :d 2}]
(println a b)
(println "Not this one"))
Destructuring binds a pattern of names to a complex object by binding each name to the corresponding part of the object.
To bind to a sequence, you present a vector of names. For example ...
(let [[x y] (list 5 7)] ... )
... is equivalent to
(let [x 5, y 7] ... )
To bind to a map or to a vector by index lookup, you present a map of name-to-key pairs. For example ...
(let [{x 0, y 1} [5 7]] ... )
... is equivalent to both of the above.
As others have mentioned, you can find a full description of this powerful mechanism here.

How to append to variable from within another function in clojure?

The question doesn't really explain what I want to do but I couldn't think of anything else.
I have an empty map in the outer let function in a piece of code, and an integer array.
I want to iterate through the integer array, perform a simple task, and keep appending the resulting map to the variables in the outer variables.
(let [a {} ;outer variables
b {}]
(doseq [x [1 2 3]]
(let [r (merge a {x (* x x)}) ;I want to append this to a
s (merge b {x (+ x x)})] ;and this to b
(println (str "--a--" r "--b--" s)))))
But as soon as I get out of doseq, my a and b vars are still empty. I get that the scope of a and b doesn't extend outside of doseq for it to persist any changes done from within and that they are immutable.
How do I calculate the values of a and b in such cases, please? I tried to extract the functionality of doseq into another function and calling let with:
(let [a (do-that-function)])
etc but even then I couldn't figure out a way to keep track of all the modifications within doseq loop to then send back as a whole.
Am I approaching this in a wrong way?
Thanks
edit
Really, what I'm trying to do is this:
(let [a (doseq [x [1 2 3]] {x (* x x)})]
(println a))
but doseq returns nil so a is going to be nil :-s
All variables in clojure are immutable. If you need a mutable state you should use atoms or refs.
But in your case you can simply switch from doseq to for:
(let [a (for [x [1 2 3]] {x (* x x)})]
(println a))
Here is an example of solving your problem with atoms:
(let [a (atom {})
b (atom {})]
(doseq [x [1 2 3]]
(swap! a assoc x (* x x))
(swap! b assoc x (+ x x)))
(println "a:" #a)
(println "b:" #b))
But you should avoid using mutable state as far as possible:
(let [l [1 2 3]
a (zipmap l (map * l l))
b (zipmap l (map + l l))]
(println "a:" a)
(println "b:" b))
The trick is to think in terms of flows of data adding to existing data making new data, instead of changing past data. For your specific problem, where a data structure is being built, reduce is typically used:
(reduce (fn [result x] (assoc result x (* x x))) {} [1 2 3])
hehe, I just noticed that "reduce" might seem confusing given that it's building something, but the meaning is that a collection of things is "reduced" to one thing. In this case, we give reduce an empty map to begin with, which binds to result in the fn, and each successive mapping over the collection results in a new result, which we add to again with assoc.
You could also say:
(into {} (map (fn [x] [x (* x x)]) [1 2 3]))
In your question you wanted to make multiple things at once from a single collection. Here's one way to do that:
(reduce (fn [[a b] x] [(assoc a x (* x x)) (assoc b x (+ x x))]) [{} {}] [1 2 3])
Here we used destructuring syntax to refer to our two result structures - just make a picture of the data [with [vectors]]. Note that reduce is still only returning one thing - a vector in this case.
And, we could generalize that:
(defn xfn [n fs]
(reduce
(fn [results x] (map (fn [r f] (assoc r x (f x x))) results fs))
(repeat (count fs) {}) (range n)))
=> (xfn 4 [* + -])
({3 9, 2 4, 1 1, 0 0} {3 6, 2 4, 1 2, 0 0} {3 0, 2 0, 1 0, 0 0})
The result is a list of maps. And if you wanted to take intermediate steps in the building of these results, you could change reduce to reductions. Generally, map for transforming collections, reduce for building a single result from a collection.

Sequentially nest vectors/list in Clojure?

How could I convert this:
[a b c d e]
or this:
(e d c b a) ;(rseq [a b c d e])
to this:
[a[b[c[d[e]]]]]
I've been wracking my brain and I feel like there is a simple solution! :-\
Ultimately I want to do this:
[a b c d e]
[a b c x y]
[a b c d j k]
as this:
{a {b {c {d {e}
{j {k}}
{x {y}}}}
Which I think conj will help with
(Update: added answer to the new question added in the edit below the answer to the original question.)
I've actually answered this very question in #clojure recently.
Here are two approaches: f is pretty much the spec directly transformed into code, which however creates a seq -- (next xs) -- which immediately gets poured into a new vector at each step; g is a much better version which only allocates objects which will actually occur in the output, plus a vector and the seq links to traverse it:
;; [1 2 3] -> [1 [2 [3]]]
;; naive, quadratic:
(defn f [xs]
(if (next xs)
[(first xs) (vec (f (next xs)))]
(vec xs)))
;; only allocates output + 1 vector + a linear number of seq links,
;; linear overall:
(defn g [v]
(reduce (fn [acc x]
[x acc])
[(peek v)]
(rseq (pop v))))
NB. I'm overlooking the usual logarithmic factors arising from vector operations (so this is soft-O complexity).
As for producing a nested map, the above isn't particularly useful. Here's one approach:
(defn h
([v]
(h nil v))
([m v]
(assoc-in m v nil)))
(h [1 2 3 4])
;= {1 {2 {3 {4 nil}}}}
(def data
'[[a b c d e]
[a b c x y]
[a b c d j k]])
(reduce h {} data)
;= {a {b {c {x {y nil}, d {j {k nil}, e nil}}}}}
I'm using nil as a "terminator", since {y} (as currently found in the answer text) is not a well-formed literal. true might be a more convenient choice if you plan to call these maps as functions to check for presence of keys.
Simpler solution here (using destructuring and non-tail recursion):
http://ideone.com/qchXZC
(defn wrap
([[a & as]]
(if-let [[b & cs] as]
[a (wrap as)]
[a])))

In clojure, how to create a list applying 2 different functions on a collection of 2-elements vectors?

In Clojure, I have a collection coll of 2-elements vectors. I would like to create the collection obtained by applying f and g on the first and second elements on every vector of the collection, respectively. I think this is related to the list comprehension construct.
(def coll [[1 1000] [2 2000] [3 3000]])
IS there an idiomatic way for creating the following result?
[[f(1) g(1000)] [f(2) g(2000)] [f(3) g(3000)]]
Again, list comprehension FTW:
(vec (for [[x y] [[1 1000] [2 2000] [3 3000]]] [(f x) (g y)]))
Yes,
(vec (map (fn [[p1 p2]] [(f p1) (g p2)])
[[1 1000] [2 2000] [3 3000]]))
To write this from scratch, I would do exactly what skuro did - it's simple, easy, and readable. But I also wrote a higher-order function to abstract this some time ago, named knit. So now I would write this as
(map (knit f g) [[1 1000] [2 2000] [3 3000]])