I'm trying to parse a nested array structure of the following form:
[element [[child1] [child2] [child3 [[subchild1] [subchild2]]]]]
I would also like to return a list with all symbols (and nothing else), regardless of nesting depth; however, I'm not looking for flatmap or flatten etc, since I need to perform more complicated additional work on every element.
This is what I came up with so far:
(defn create-element [rs element]
(if (symbol? element)
(cons element rs)
rs))
(defn parse
([rs element] (create-element rs element))
([rs element [children & more]] (if (nil? more)
(parse (parse rs element) (first children))
(parse (parse rs element) (first children) more))))
(defn n-parse [element]
(apply parse () element))
This works fine for the following input:
=> (n-parse ['bla [['asd] ['kkk] ['sss]]])
(sss kkk asd bla)
But this doesn't work:
=> (n-parse ['bla [['asd] ['kkk [['ooo]]] ['sss]]])
(sss kkk asd bla)
I'm still trying to wrap around my head around the types but can't seem to manage to get it right. For example, Haskell makes this easy with pattern matching etc, whereas Clojure doesn't allow same arity function overloading.
Also is there a more concise / idiomatic way (without having to resort to if?) I'd prefer pure Clojure solutions (no external libs) since this is actually for a Clojurescipt project.
Many thanks for any help!
I don't see whats wrong with flatten. If you want to do some work on the items first, do the work first and then flatten the result:
(defn map-tree
"Example: (map-tree + [1 2 [3 5]] [3 4 [5 6]])"
[f & trees]
(if (every? coll? trees)
(apply map (partial map-tree f) trees)
(apply f trees)))
(defmulti transformator identity)
;; transform 'sss element into something special
(defmethod transformator 'sss [_] "sss")
;; default transformation
(defmethod transformator :default [v] v)
Test:
user> (flatten (map-tree transformator '[bla [[asd] [kkk] [sss]]]))
(bla asd kkk "sss")
user>
Would that not work?
Related
I've been writing out a function in Clojure that would take a row of a 2d array and then multiples the values in it by a single value. I have the index to get the specific row and the value to multiply the row with in another array.
The function will return the array, that has now got values multipled by the single value.
Here's the code:
(def twod-array [[3.1 0.0023 0.35]
[0.21 0.00353 8.13]])
(def iandv [1 3.1])
(defn array-multiply [iandv twod-array]
(
let [array-row (nth twod-array (nth iandv 0))]
(map * [array-row] [(nth iandv 1)])
)
The let gets the array row and then it will return the row with the values inside multiplied with the value of the "index and value" array.
This has the closest I've gotten using the examples with the clojure.doc website and I'm getting a ClassCastException of the following:
ClassCastException clojure.lang.PersistentVector cannot be cast to java.lang.Number clojure.lang.Numbers.multiply (Numbers.java:148)
I've been looking at map vector and other map functions but I haven't been able to find a good solution.
more clojurish way could look something like this:
(defn array-multiply [[row mul] twod-array]
(update twod-array row #(mapv (partial * mul) %)))
user> (array-multiply iandv twod-array)
;;=> [[3.1 0.0023 0.35] [0.651 0.010943000000000001 25.203000000000003]]
Your code is somewhat hard to read, but basically, you're trying to multiply a number and a vector, that doesn't work.
(defn array-multiply [iandv twod-array]
(let [array-row (nth twod-array (nth iandv 0))]
(map * array-row [(nth iandv 1)])))
works since array-row already is a vector.
I'm trying to fill a Clojure vector with values from a map.
I have another vector of specific keys in the map the store the values I need.
I need to iterate the key-vec, get the values from the map and store them in another vector.
I've tried using loop+recur:
(let [keys-vec (:keys-vec item)
my-map (:my-map item)]
(loop [newV []
i 0]
(if (< i (count keys-vec))
(recur
(conj newV (get my-map (get keys-vec i)))
(inc i))
newV)))
And it worked.
But I know Clojure is known for it's minimalistic/efficient code writing style and I wanted to know whether there's a better way.
Any ideas?
I'd say, that the most idiomatic way will be to use original vector. I don't see any reason to explicitly clone an immutable datastructure.
You want the select-keys function to extract only the keys of interest from your map. See: http://clojuredocs.org/clojure.core/select-keys
Then, use the vals function to extract all of the values from the filtered map:
> (def my-map {:a 1 :b 2 :c 3})
> (def my-keys [:a :b])
> (select-keys my-map my-keys)
{:a 1, :b 2}
> (def filtered-map (select-keys my-map my-keys))
> filtered-map
{:a 1, :b 2}
> (vals filtered-map)
(1 2)
You should keep a browser tab open to the Clojure Cheatsheet at all times. It is invaluable for finding the functions you want. Keep studying it repeatedly, as you'll keep finding new things for years. This is my favorite version:
http://jafingerhut.github.io/cheatsheet/clojuredocs/cheatsheet-tiptip-cdocs-summary.html
Using Alan Thompson's example:
(def my-map {:a 1 :b 2 :c 3})
(def my-keys [:a :b])
... a simple and fast solution is
(mapv my-map my-keys)
;[1 2]
The alternative
(vals (select-keys my-map my-keys))
;(2 1)
... may not (and, in this case, does not) maintain the order given by my-keys.
This question already has answers here:
How do I create a primitive two-dimensional (2d) array of doubles in Clojure?
(2 answers)
Closed 6 years ago.
I have a 2D vector like
(def data [[1 1] [1 1]])
I would like to turn it into double[][].
i examined clojure.core and I tried :
1)
(->> (map double-array data)
(to-array-2d))
Unfortnately it returns Object[][] type of data, which fails in Java interop.
2)
(->> (map double-array data)
(double-array))
Of course it does not work because double-array expects a collection of numbers
3) I did not code it since it's heavy and I do not know if something esle exist but I could initialize a double[][] with (make-array Double/Type 2 2) [2 2 got by alen] and then fill it with loops.
Like in Java in fact.
4) A short way but a bit twisted
(def double-2d-array-type
(type (double-array [])))
(->> (map double-array data)
(into-array double-2d-array-type)))
Is there a direct way ? If it was possible to call directly double[] it would be better.
Like "(into-array double[] data)"
Just remove the first argument to into-array:
(into-array (map double-array data))
As long as there is at least one element in the input sequence, into-array can look at its type to guess the desired type of the output array. This guess isn't always what you want, because of inheritance, but for primitives it will never be wrong.
generally i want to know when we have array of object that have some property can same the "Object Literal in JavaScript" can calculated with specific function. i want to create that property for my array in clojure to apply some calculation on them such as sorting or more simpler finding maximum according to that property.for example how try find maximum in this example?
(def aSqh (fn [x] (* x x)))
(def maSqh (max (apply aSqh [1 2 3 4])))
the have error that output is object and not number
You seem to be thinking of a mapping operation (take a function of one argument and a collection, replace every element with the result of the function on that element), which in Clojure is called map. apply is a function for plumbing collections into functions as if they were given each element as a separate argument. Usually you want to use it with variadic functions (i.e. functions such as max, that take a variable number of arguments). For instance
(def maSqh (apply max (map aSqh [1 2 3 4]))) ;;=> 16
If you want to preserve the datatype of a collection after performing a mapping, you can use into and empty:
(defn preserving-map [f coll]
(into (empty coll) (map f coll)))
(preserving-map aSqh [1 2 3 4]) ;;=>[1 4 9 16]
(preserving-map aSqh #{1 2 3 4}) ;;=> #{1 4 9 16}
but this removes the (useful) laziness that map usually gives us. For the particular case of vectors (like [1 2 3 4]), this use case is common enough that there is mapv which eagerly performs mappings and puts them into a vector.
Is there any simplier way to find the last element of an array in clojure except this function?
(fn [l] (if (empty? (rest l)) (first l) (recur (rest l))))
For vectors, use peek for constant time
user=> (peek [1 2 3 4 5])
5
For Java arrays,
user=> (let [a (to-array [1 2 3 4 5])] (aget a (dec (alength a))))
5
For a general collection, you can get the last item in linear time with last. It is defined similarly to what you have done.
user=> (source last)
(def
^{:arglists '([coll])
:doc "Return the last item in coll, in linear time"
:added "1.0"
:static true}
last (fn ^:static last [s]
(if (next s)
(recur (next s))
(first s))))
The simplest way is to use (last l) that works in linear time (http://clojure.github.io/clojure/clojure.core-api.html#clojure.core/last)
Another possibility is to reverse your collection and take the first element: ((comp first reverse) l). But that's rather slow as reverse returns a non-lazy sequence. Note: comp returns a composition of its arguments (functions) (http://clojure.github.io/clojure/clojure.core-api.html#clojure.core/comp)
You can also convert the collection to a vector first and then apply peek: ((comp peek vec) l). This should have a better performance.
Another one: determine the length of your collection and take the last element (#(nth % (dec (count %))) l).
These functions work for all collection types (e.g. vectors, lists, ...). There are no arrays per se in Clojure (except you want to use Java arrays).