Raising elements in a vector to a power - clojure

I am trying to input a vector and parameter p, which in turn should raise each element of the vector to the power p. So far I have tried mapping the numeric tower function power, but that has proved unsuccessful. What would be the easiest way to raise each element of a vector to a power p?
(defn p' [x p]
(map power x p))

You need something like:
(defn compute [exp numbers]
(map #(power exp %) numbers))
For more information, type the following in your REPL:
(doc map)

To expand on Chiron's answer, you could also do with partial application:
(defn compute [exp numbers]
(map (partial power exp) numbers))

Related

map-indexed alternative for reducers

Is there a map-indexed alternative for clojure.core.reducers? I would like something that would work lazily like r/map (without constructing new sequence).
I suspect that what you really want to use is a transducer, since map-indexed has a 1-arity version (as does map, filter, and many other core functions) that returns a transducer. Transducers are composable, and do not create an intermediate sequence. Here is a short example:
(def xf (comp
(map-indexed (fn [i value] [i value]))
(filter (fn [[i value]] (odd? i)))
(map second)))
This says: generate an indexed vector using map-indexed, filter out only the vectors whose index is odd, and get the second element. It's a long-winded way of saying (filter odd? collection) but it's only for example purposes.
You can use this with into:
(into [] xf "ThisIsATest")
=> [\h \s \s \T \s]
or you can use the transduce function and apply str to the result:
(transduce xf str "ThisIsATest")
=> "hssTs"

can't use vector creation inside short-hand function definition

I'd like to do vector creation inside a function.
(map #([first %]) coll_of_tuples)
This gives the error
ArityException Wrong number of args (0) passed to: PersistentVector
clojure.lang.AFn.throwArity (AFn.java:429)
Any workaround besides using list? I'm looking for short notation.
If you want a shorter version there is a few options:
(map #(-> [(first %)]) coll)
(map #(do [(first %)]) coll)
(map (juxt first) coll)
I like peter's answer in the comments of
(map #(vector (first %)) coll_of_tuples)
Or alternately
(map #(-> % first vector) coll_of_tuples)
Or leaning on FP more and anon fn less:
(map (comp vector first) coll_of_tuples)
If you instead prefer to think of this as extracting the first 1-length sequence from each, this is a seq-ier answer:
(map #(take 1 %) coll_of_tuples)
If I needed the vector type I'd use (map #(vector (first %)) coll_of_tuples) as suggested by peter. So far it appears that list is the shortest notation.
You could also use for, which is very similar to map except for giving a symbolic name to each element of the sequence in turn:
(for [tuple coll_of_tuples]
[(first tuple)])
This is not quite as minimal as some of the other solutions, but in some instances it is nice to have a named symbol like tuple instead of %.

clojure: filtering a vector of maps by keys existence and values

I have a vector of maps like this one
(def map1
[{:name "name1"
:field "xxx"}
{:name "name2"
:requires {"element1" 1}}
{:name "name3"
:consumes {"element2" 1 "element3" 4}}])
I'm trying to define a functions that takes in a map like {"element1" 1 "element3" 6} (ie: with n fields, or {}) and fiters the maps in map1, returning only the ones that either have no requires and consumes, or have a lower number associated to them than the one associated with that key in the provided map (if the provided map doesn't have any key like that, it's not returned)
but I'm failing to grasp how to approach the maps recursive loop and filtering
(defn getV [node nodes]
(defn filterType [type nodes]
(filter (fn [x] (if (contains? x type)
false ; filter for key values here
true)) nodes))
(filterType :requires (filterType :consumes nodes)))
There's two ways to look at problems like this: from the outside in or from the inside out. Naming things carefully can really help when working with nested structures. For example, calling a vector of maps map1 may be adding to the confusion.
Starting from the outside, you need a predicate function for filtering the list. This function will take a map as a parameter and will be used by a filter function.
(defn comparisons [m]
...)
(filter comparisons map1)
I'm not sure I understand the comparisons precisely, but there seems to be at least two flavors. The first is looking for maps that do not have :requires or :consumes keys.
(defn no-requires-or-consumes [m]
...)
(defn all-keys-higher-than-values [m]
...)
(defn comparisons [m]
(some #(% m) [no-requires-or-consumes all-keys-higher-than-values]))
Then it's a matter of defining the individual comparison functions
(defn no-requires-or-consumes [m]
(and (not (:requires m)) (not (:consumes m))))
The second is more complicated. It operates on one or two inner maps but the behaviour is the same in both cases so the real implementation can be pushed down another level.
(defn all-keys-higher-than-values [m]
(every? keys-higher-than-values [(:requires m) (:consumes m)]))
The crux of the comparison is looking at the number in the key part of the map vs the value. Pushing the details down a level gives:
(defn keys-higher-than-values [m]
(every? #(>= (number-from-key %) (get m %)) (keys m)))
Note: I chose >= here so that the second entry in the sample data will pass.
That leaves only pulling the number of of key string. how to do that can be found at In Clojure how can I convert a String to a number?
(defn number-from-key [s]
(read-string (re-find #"\d+" s)))
Stringing all these together and running against the example data returns the first and second entries.
Putting everything together:
(defn no-requires-or-consumes [m]
(and (not (:requires m)) (not (:consumes m))))
(defn number-from-key [s]
(read-string (re-find #"\d+" s)))
(defn all-keys-higher-than-values [m]
(every? keys-higher-than-values [(:requires m) (:consumes m)]))
(defn keys-higher-than-values [m]
(every? #(>= (number-from-key %) (get m %)) (keys m)))
(defn comparisons [m]
(some #(% m) [no-requires-or-consumes all-keys-higher-than-values]))
(filter comparisons map1)

Map over first element of list of vectors

How can I map a function over just the first elements of vectors in a list?
So I have
(["1" "sometexthere" ...]["2" "somemoretext" ...] ....)
I need to use read-string to convert the stringy numbers into ints (or longs).
If you want just the list of results, you can combine the function with first and map it, as #leetwinski recommended in the comments.
(map #(clojure.edn/read-string (first %)) items)
If you want to get back the structure you had, but with those particular elements mapped by the function, update and update-in are your friends:
(map #(update % 0 clojure.edn/read-string) items)
For more involved transformations you may also be interested in specter's transform.
You can use comp to compose functions:
(require '[clojure.edn :as edn])
(def items [["1" "sometexthere" ,,,] ["2" "somemoretext" ,,,] ,,,])
(map (comp edn/read-string first) items)
;=> (1 2 ,,,)
I like the comp solution by Elogent, however I think for readability I prefer the use of a threading macro:
(map #(-> % first clojure.edn/read-string) items)
To each his/her own, just my personal preference.

Assoc-if in Clojure

Is there an "assoc-if" function in the Clojure library? I.e if a value is truthy, update a map with a given key value. I've tried to find something to this effect, but came up lacking.
(defn assoc-if
[m key value]
(if value (assoc m key value) m))
If the goal is to avoid repeating m, you can use conj:
(conj m (when value [key value]))
...or Clojure 1.5's new threading macros:
(-> m
(cond-> value (assoc key value)))
If it's actually important to avoid repeating both the m and value, you'll have to write your own or reach outside clojure.core
There is no build-in assoc-if function in Clojure, but you're not the first one who needs it. Check this link with an implementation of assoc-if by ALEX MILLER:
(defn ?assoc
"Same as assoc, but skip the assoc if v is nil"
[m & kvs]
(->> kvs
(partition 2)
(filter second)
flatten
(apply assoc m)))
But, since flatten is recursive, it's best to replace it with something which is not (thanks to kotarak for the hint). Another problem of this implementation is that (apply assoc m) will fail on empty list. So, it's best to replace it to:
(defn ?assoc
"Same as assoc, but skip the assoc if v is nil"
[m & kvs]
(->> kvs
(partition 2)
(filter second)
(map vec)
(into m)))
Just use assoc-some from the medley library. Battle-tested and widely used.