What is the right way of turning a flat list like this:
(1 2 3 4 5 6 7 8 9)
into a sequence of vectors:
([1 2 3] [4 5 6] [7 8 9])
Sorry, I suppose this is something right out of the toolbox, but I can't think of the right keyword.
(->> '(1 2 3 4 5 6 7 8 9) (partition 3) (map vec))
Take the original list and then partition it by 3 and finally map each partition to a vector.
I think using the ->> macro makes it read nicer.
user> (def flat-seq (range 1 10))
#'user/flat-seq
user> (map vec (partition-all 3 flat-seq))
;=> ([1 2 3] [4 5 6] [7 8 9])
Related
I understand how map works but I am confused by this example:
(def check-sum
(fn [sequence]
(apply + (map *
(range 1 (inc (count sequence)))
sequence))))
The map part looks like this when given a sequence:
(map * (range 1 (inc (count [5 1 1 4 7 7 1 3 1 0]))) [5 1 1 4 7 7 1 3 1 0])
Which returns this:
(5 2 3 16 35 42 7 24 9 0)
I do not understand where the current item in the map is being multiplied. I would understand if it was using an anonymous function of the form #(* %) etc.
But there is no anonymous function in this example.
The first argument of map should be function and the number of parameter should be matched to the number of collections provided. So, if you want to pass an anonymous function, you should write the code like this:
(map #(* %1 %2) [1 3 5] [2 4 6])
;=> (2 12 30)
(map #(* %1 %2 %3) [1 3 5] [2 4 6] [3 5 7])
;=> (6 60 210)
But * itself is a function which can take any number of arguments (check (doc *) from REPL), you can write the code in a simpler form:
(map * [1 3 5] [2 4 6])
;=> (2 12 30)
(map * [1 3 5] [2 4 6] [3 5 7])
;=> (6 60 210)
* is applied to the set of first elements of each collection, set of second elements, ...
Other functions like +, -, / can be used in this way, too.
No anonymous function is needed, because the named function * is what's doing the multiplying. Two collections are passed to map, so it passes the corresponding elements from each collection to the * function.
Consider the following function as an example:
(defn f [x y] (+ x y))
I want to use this function to add 2 to each element of a vector:
[1 2 6 3 6]
I can use map:
(map f [1 2 6 3 6] [2 2 2 2 2])
But it seems a little ugly creating the second vector where every element is exactly the same.
So I thought using a closure was a better approach:
(map (fn g [x] (f x 2)) [1 2 6 3 6])
So my question is:
In clojure, what is the best way to use map when some arguments are not changing?
Just apply partial function
(map (partial + 2) [1 2 6 3 6]) => (3 4 8 5 8)
Approach 1: use repeat.
(repeat 2) gives you a lazy sequence of infinite 2s
In your case,
(map f [1 2 6 3 6] [2 2 2 2 2])
should be converted into
(map f [1 2 6 3 6] (repeat 2))
Approach 2: use anonymous function
(map #(f % 2) [1 2 6 3 6])
Given a nested vector A, which is the 3 x 4 matrix
[[1 4 7 10] [2 5 8 11] [3 6 9 12]]
Transform A such that the nested vector (matrix) is now 2 x 6.
The output would look like
[[1 3 5 7 9 11] [2 4 6 8 10 12]]
As of now I am stuck on the beginning implementation of this idea.
You might want to look into core.matrix:
;; using [net.mikera/core.matrix "0.18.0"] as a dependency
(require '[clojure.core.matrix :as matrix])
(-> [[1 4 7 10] [2 5 8 11] [3 6 9 12]]
(matrix/transpose)
(matrix/reshape [6 2])
(matrix/transpose))
;= [[1 3 5 7 9 11] [2 4 6 8 10 12]]
this function will reshape m to be composed of subvectors with the desired shape
(defn reshape [m & shape]
(reduce (fn [vecs dim]
(reduce #(conj %1 (subvec vecs %2 (+ dim %2)))
[] (range 0 (count vecs) dim)))
(vec (flatten m)) (reverse shape)))
example:
(reshape [1 [2 3 4] 5 6 7 8] 2 2) => [[[1 2] [3 4]] [[5 6] [7 8]]]
The following line: (repeat 4 [2 3])
gives me this: ([2 3] [2 3] [2 3] [2 3])
How do I create one vector or list from the above list of vectors so that I get this?: [2 3 2 3 2 3 2 3]
Thanks
concat is in fact exactly the function you want
user> (apply concat (repeat 4 [2 3]))
(2 3 2 3 2 3 2 3)
this even works with lazy input:
user> (take 8 (apply concat (repeat [2 3])))
(2 3 2 3 2 3 2 3)
This is an alternative:
user> (def flatten-1 (partial mapcat identity))
#'user/flatten-1
user> (flatten-1 (repeat 4 [2 3]))
(2 3 2 3 2 3 2 3)
it is compatible with laziness and unlike flatten preserves any substructure (only doing one level of flattening)
user> (take 12 (flatten-1 (repeat [2 3 [4]])))
(2 3 [4] 2 3 [4] 2 3 [4] 2 3 [4])
(take 8 (cycle [2 3]))
;; => (2 3 2 3 2 3 2 3)
(flatten x)
Takes any nested combination of sequential things (lists,
vectors, etc.) and returns their contents as a single, flat sequence.
(flatten nil) returns nil.
(flatten (repeat 4 [2 3])) ;(2 3 2 3 2 3 2 3)
Pedantically speaking, you asked for a vector, so:
(->> [2 3] cycle (take 8) vec)
I feel cycle is a little more appropriate than concat (though it uses concat itself) as it indicates "cycle through the elements of this sequence" rather than "concatenate the following sequences together". Just my two cents, matter of opinion.
I have a vector - [1 2 3 4]
I want to check that in the vector each element appears only once. How do I do it ? One way I can think of is to convert it into a set and then back into the vector and then compare both :) However I think there should be a simpler way ...
You can use distinct?:
(apply distinct? [1 2 3 4]) ;=> true
(apply distinct? [1 2 3 4 4]) ;=> false
You can use distinct:
(distinct [1 2 3 4 5 5]) -> [1 2 3 4 5]
For a check, you can do something like:
(= [1 2 3 4 5 5] (distinct [1 2 3 4 5 5]))