I'm trying to sort a map over the values.
The input-map looks like:
{:Blabla 1, :foo 1, :bla-bla 1, :Bla 2, :bla/bla 1, :bla 4, :blub 2, :hello 1, :Foo 2}
The output should look like:
{:bla 4 :Bla 2 :blub 2 :Foo 2 :Blabla 1 :bla-bla 1 :bla/bla 1 :foo 1 :hello 1}
I used sorted-map-by like in the documentation here:
http://clojuredocs.org/clojure.core/sorted-map-by
(defn sort-keyword-list [texts]
(let [results (word-counts texts)]
;results is now {:Blabla 1, :foo 1, :bla-bla 1, :Bla 2, :bla/bla 1, :bla 4, :blub 2, :hello 1, :Foo 2}
(into (sorted-map-by (fn [key1 key2]
(compare [(get results key2) key2]
[(get results key1) key1])))
results))
)
Well I found out that this solution works only if the keywords have no special characters like "/" or "-" inside. Is this a known bug?
So how can I sort a map by values quickly without writing a own and slowly sort-algorithm?
In my Clojure 1.6.0 REPL, the code in the question already sorts by value:
user=> (into (sorted-map-by (fn [key1 key2]
(compare [(get x key2) key2]
[(get x key1) key1])))
x)
{:bla 4, :blub 2, :Foo 2, :Bla 2, :bla/bla 1, :hello 1, :foo 1, :bla-bla 1, :Blabla 1}
If you want entries with the same value to be sorted by key, you need to stringify the keys. Here's why:
user=> x
{:bla-bla 1, :Blabla 1, :bla/bla 1, :hello 1, :bla 4, :foo 1, :Bla 2, :Foo 2, :blub 2}
user=> (sort (keys x))
(:Bla :Blabla :Foo :bla :bla-bla :blub :foo :hello :bla/bla)
user=> (sort (map str (keys x)))
(":Bla" ":Blabla" ":Foo" ":bla" ":bla-bla" ":bla/bla" ":blub" ":foo" ":hello")
Here is a solution based on the suggestion by #user100464 with explicit considerations of comparison of keys, when the values are the same.
Note: I choose to sort decreasingly by reversing the order of the arguments to the comparisons: (compare (x k2) (x k1)) and (compare k2 k1).
(defn sort-by-value-then-key [x]
(into (sorted-map-by (fn [k1, k2]
(let [v_c (compare (x k2) (x k1))]
(if (= 0 v_c)
(compare k2 k1)))))
x))
One may customize at (compare k2 k1) to implement more elaborate key comparison.
Related
Here's some code for a cartesian product, it can be two lists, two vectors, or any number of combinations of the two. I'd really appreciate help with the second, fourth, and final lines, explaining what each line is doing
(defn cartesian-product ;function name definition
([] '(())) ;need help understanding this
([xs & more] ; at least two variables, xs is one of them
(mapcat #(map (partial cons %) ;mapcat means a create a concatenated map of the following
;still trying to figure out partial, but cons takes a
;variable and puts it in front of a sequence
(apply cartesian-product more)) ; this is the sequence that is mapped
; using (partial cons %)
xs))) ;not sure what this is here for
Here is a reworked version that illustrates what is going on (and how):
(ns tst.demo.core
(:use demo.core tupelo.core tupelo.test))
;----------------------------------------------------------------------------
; Lesson: how map & mapcat work
(defn dup [x]
"Return 2 of the arg in a vector"
[x x])
(dotest
(let [nums [0 1 2]]
(is= (mapv inc nums) [1 2 3])
(is= (mapv dup nums) [[0 0] ; like a matrix, 2-D
[1 1]
[2 2]])
; mapcat glues together the inner "row" vectors. So the result is 1-D instead of 2-D
(is= (mapcat dup nums) [0 0 1 1 2 2])))
then the reworked code
;----------------------------------------------------------------------------
(def empty-matrix [[]]) ; 0 rows, 0 cols
(defn cartesian-product ;function name definition
"When called with 1 or more sequences, returns a list of all possible combinations
of one item from each collection"
([] ; if called with no args
empty-matrix) ; return an empty matrix
; if called with 1 or more args,
([xs ; first arg is named `xs` (i.e. plural for x values)
& more] ; all other args are wrapped in a list named `more`
(let [recursion-result (apply cartesian-product more) ; get cartesian prod of sequences 2..N
inner-fn (fn [arg] (map ; for each recursion-result
(partial cons arg) ; glue arg to the front of it
recursion-result))
; for each item in the first sequence (xs), glue to front of
; each recursion result and then convert 2D->1D
output (mapcat inner-fn xs)]
output)))
and some unit tests to show it in action
(dotest
(is= (cartesian-product [1 2 3]) [[1] [2] [3]])
(is= (cartesian-product [1 2 3] [:a :b])
[[1 :a]
[1 :b]
[2 :a]
[2 :b]
[3 :a]
[3 :b]])
(is= (cartesian-product [1 2 3] [:a :b] ["apple" "pea"])
[[1 :a "apple"]
[1 :a "pea"]
[1 :b "apple"]
[1 :b "pea"]
[2 :a "apple"]
[2 :a "pea"]
[2 :b "apple"]
[2 :b "pea"]
[3 :a "apple"]
[3 :a "pea"]
[3 :b "apple"]
[3 :b "pea"]]))
This code is written in a functional programming style.
Below is how this should work.
(permutations ‘(a b c)) --> ((a b c) (a c b) (b a c) (b c a) (c a b) (c b a))
Please explain how fold and map work in this code and also recursive permutation...
def map(f, lst)
lst.map{|v| f.call(v)}
end
def fold(f, init, lst)
lst.reduce(init){|w, a| f.call(w, a)}
end
def permutations(lst)
lst.empty? ? [[]] : fold(lambda{|w, a| w + a}, [], map(lambda{|v| map(lambda{|p| [v]+p}, permutations(lst-[v]))}, lst))
end
Let me give this a shot.
def map(f, lst)
lst.map{|v| f.call(v)}
end
map takes an array lst and applies a function f on each element of lst.
The following example doubles each element of an array.
irb(main):007:0> map(lambda {|i| i * 2}, [1,2,3])
=> [2, 4, 6]
Next,
def fold(f, init, lst)
lst.reduce(init){|w, a| f.call(w, a)}
end
fold takes an array lst, an initial value init, applies function f on each element of lst and combines it with the previous result to return a value. The result of f.call(w, a) is stored in w. w has an initial value of init.
In plain ruby,
w = init
lst.each do |a|
w = f.call(w, a)
end
return w
In the following example, fold takes the sum of the array by adding each element.
irb(main):010:0> fold(lambda {|a, i| a + i}, 0, [1,2,3])
=> 6
Now, the main function,
def permutations(lst)
lst.empty? ? [[]] : fold(lambda{|w, a| w + a}, [], map(lambda{|v| map(lambda{|p| [v]+p}, permutations(lst-[v]))}, lst))
end
The first part is easy. If lst is empty, return [[]].
The second part is
fold(lambda{|w, a| w + a}, [], map(lambda{|v| map(lambda{|p| [v]+p}, permutations(lst-[v]))}, lst))
We'll work backwards from the innermost.
map(lambda{|p| [v]+p}, permutations(lst-[v]))
This is simple. For each element returned by permutations, we append [v] (v is defined in the outer map). permutations takes the array minus the element v.
Here's one example.
irb(main):012:0> permutations([1,2,3]-[3])
=> [[1, 2], [2, 1]]
irb(main):013:0> map(lambda{|p| [3]+p}, permutations([1,2,3] - [3]))
=> [[3, 1, 2], [3, 2, 1]]
Next we go one step higher where we see that the v in the inner map is each element from lst.
map(lambda{|v| map( ... )}, lst)
In plain ruby, this is basically
lst.map do |v|
a = permutations(lst - [v])
a.map {|p| [v] + p}
end
Finally, we have
fold(lambda{|w, a| w + a}, [], map( ... ))
For each element in the array returned by map, we add it to w which is initially an empty array [].
irb(main):019:0> fold(lambda {|w, a| w + a}, [], [[[1, 2]], [[2, 1]]])
=> [[1, 2], [2, 1]]
If you want to know why this algorithm works, consider the patterns.
irb(main):021:0> permutations([1,2,3])
=> [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
which is same as
irb(main):023:0> permutations([1,2]).map {|i| i + [3]}
=> [[1, 2, 3], [2, 1, 3]]
irb(main):024:0> permutations([1,3]).map {|i| i + [2]}
=> [[1, 3, 2], [3, 1, 2]]
irb(main):025:0> permutations([2,3]).map {|i| i + [1]}
=> [[2, 3, 1], [3, 2, 1]]
Please explain how fold and map work in this code
Those are simply message sends (in other languages they are called method calls). They are calling the methods named fold and map, respectively.
and also recursive permutation...
The permutation method uses the methods named fold and map. There is no definition for those methods, so this will simply raise a NoMethodError.
I need to create random numbers and store them into a variable for multiple calculations and for different calls.
(defn position
(def x (rand-int 2147483647))
(def y (rand-int 2147483647))
(def z (rand-int 2147483647))
)
What I want to do is calling this function in a loop, do calculations with it and store this away.
Anyone could help, please? There is probably a better way.
If you want an arbitrary number of things, you need to use an arbitrarily sized data structure. In this case you can probably use the function repeatedly:
(repeatedly 5 #(rand-int 2147483647))
In this example we take 5 elements (you can change to as many as you need) from repeatedly running the anonymous no-arguments function #(rand-int 2147483647) which is what you seem to need.
To generate an infinite lazy sequence of random ints you can use:
(repeatedly #(rand-int 2147483647))
To generate many positions you can also use repeatedly:
(defn rand-position []
{:x (rand-int 2147483647)
:y (rand-int 2147483647)
:z (rand-int 2147483647)})
(def positions (repeatedly rand-position))
(take 5 positions) ;; will generate 5 random positions, each represented as a map
With functional programming, I won't suggest you go down the path of defining global variables (using def). It is better to design your functions to operate on some data structure and returns the same or yet other data structure. In your case, the data-structure is called position. Given it is not a primitive (like integer), you have to decide how to model it. With Clojure, you can either pick a vector or a map for it then all your functions have to follow. Here is how I would go through this development process:
Warning: long reply ahead...
Prologue
(require '[clojure.spec.alpha :as s])
(require '[clojure.spec.gen.alpha :as gen])
(def gen-samples
"A function to create a generator, and to generate
some samples from it in one step"
(comp gen/sample s/gen))
Spec out your data structure
;; dimension is an integer between 0 to 2147483647
(s/def ::dim (s/int-in 0 2147483647))
(gen-samples ::dim)
;; => (1 0 2 1 0 0 2 0 0 27)
;; Option 1: position as a collection of 3 dimensions
(s/def ::position (s/coll-of ::dim :count 3))
(gen-samples ::position)
;; => ([0 0 0] [0 0 0] [1 0 0] [0 1 1] [1 0 1] [3 2 1] [26 1 0] [7 1 1] [6 24 1] [2 0 21])
;; Option 2: position as a map - with x,y,z as keys and with dimension as values
(s/def ::x ::dim)
(s/def ::y ::dim)
(s/def ::z ::dim)
(s/def ::position (s/keys :req-un [::x ::y ::z]))
(gen-samples ::position)
;; => ({:x 1, :y 1, :z 0} {:x 0, :y 0, :z 0} {:x 1, :y 2, :z 1} {:x 1, :y 2, :z 0} {:x 2, :y 2, :z 5} {:x 4, :y 1, :z 13} {:x 4, :y 8, :z 7} {:x 2, :y 5, :z 10} {:x 22, :y 3, :z 4} {:x 124, :y 1, :z 8})
Assuming you take option 2, now spec out your function
;; in this case, move-east is a function which takes a position
;; and returns another position - with x-dimension of the
;; new position always greater than the old one
(s/fdef move-east
:args (s/cat :pos ::position)
:ret ::position
:fn #(> (-> % :ret :x) (-> % :args :pos :x)))
Implementation - the easy part
(defn move-east [pos]
(update pos :x inc))
Some manual test
(-> ::position gen-samples first)
;; => {:x 1, :y 1, :z 0}
(move-east *1)
;; => {:x 2, :y 1, :z 0}
Auto test based on the spec
(require '[clojure.spec.test.alpha :as stest])
(-> `move-east
stest/check
stest/summarize-results)
;; => {:total 1, :check-passed 1}
;; what if my function is wrong?
(defn move-east [pos]
(update pos :x dec))
(-> `move-east
stest/check
stest/summarize-results)
;; => {:total 1, :check-failed 1}
;; what is wrong?
(-> `move-east
stest/check
first
stest/abbrev-result)
;; which basically returns a result like below...
;; showing return x is -1 and hence fails the ::dim spec
{:clojure.spec.alpha/problems
({:path [:ret :x],
:pred
(clojure.core/fn
[%]
(clojure.spec.alpha/int-in-range? 0 2147483647 %)),
:val -1,
:via [:play/dim],
:in [:x]}),
:clojure.spec.alpha/failure :check-failed}
I'm having a problem stringing some forms together to do some ETL on a result set from a korma function.
I get back from korma sql:
({:id 1 :some_field "asd" :children [{:a 1 :b 2 :c 3} {:a 1 :b 3 :c 4} {:a 2 :b 2 :c 3}] :another_field "qwe"})
I'm looking to filter this result set by getting the "children" where the :a keyword is 1.
My attempt:
;mock of korma result
(def data '({:id 1 :some_field "asd" :children [{:a 1 :b 2 :c 3} {:a 1 :b 3 :c 4} {:a 2 :b 2 :c 3}] :another_field "qwe"}))
(-> data
first
:children
(filter #(= (% :a) 1)))
What I'm expecting here is a vector of hashmaps that :a is set to 1, i.e :
[{:a 1 :b 2 :c 3} {:a 1 :b 3 :c 4}]
However, I'm getting the following error:
IllegalArgumentException Don't know how to create ISeq from: xxx.core$eval3145$fn__3146 clojure.lang.RT.seqFrom (RT.java:505)
From the error I gather it's trying to create a sequence from a function...though just not able to connect the dots as to why.
Further, if I separate the filter function entirely by doing the following:
(let [children (-> data first :children)]
(filter #(= (% :a) 1) children))
it works. I'm not sure why the first-thread is not applying the filter function, passing in the :children vector as the coll argument.
Any and all help much appreciated.
Thanks
You want the thread-last macro:
(->> data first :children (filter #(= (% :a) 1)))
yields
({:a 1, :b 2, :c 3} {:a 1, :b 3, :c 4})
The thread-first macro in your original code is equivalent to writing:
(filter (:children (first data)) #(= (% :a) 1))
Which results in an error, because your anonymous function is not a sequence.
The thread-first (->) and thread-last (->>) macros are always problematical in that it is easy to make a mistake in choosing one over the other (or in mixing them up as you have done here). Break down the steps like so:
(ns tstclj.core
(:use cooljure.core) ; see https://github.com/cloojure/tupelo/
(:gen-class))
(def data [ {:id 1 :some_field "asd"
:children [ {:a 1 :b 2 :c 3}
{:a 1 :b 3 :c 4}
{:a 2 :b 2 :c 3} ]
:another_field "qwe"} ] )
(def v1 (first data))
(def v2 (:children v1))
(def v3 (filter #(= (% :a) 1) v2))
(spyx v1) ; from tupelo.core/spyx
(spyx v2)
(spyx v3)
You will get results like:
v1 => {:children [{:c 3, :b 2, :a 1} {:c 4, :b 3, :a 1} {:c 3, :b 2, :a 2}], :another_field "qwe", :id 1, :some_field "asd"}
v2 => [{:c 3, :b 2, :a 1} {:c 4, :b 3, :a 1} {:c 3, :b 2, :a 2}]
v3 => ({:c 3, :b 2, :a 1} {:c 4, :b 3, :a 1})
which is what you desired. The problem is that you really needed to use thread-last for the filter form. The most reliable way of avoiding this problem is to always be explicit and use the Clojure as-> threading form, or, even better, it-> from the Tupelo library:
(def result (it-> data
(first it)
(:children it)
(filter #(= (% :a) 1) it)))
By using thread-first, you accidentally wrote the equivalent of this:
(def result (it-> data
(first it)
(:children it)
(filter it #(= (% :a) 1))))
and the error reflects the fact that the function #(= (% :a) 1) can't be cast into a seq. Sometimes, it pays to use a let form and give names to the intermediate results:
(let [result-map (first data)
children-vec (:children result-map)
a1-maps (filter #(= (% :a) 1) children-vec) ]
(spyx a1-maps))
;;-> a1-maps => ({:c 3, :b 2, :a 1} {:c 4, :b 3, :a 1})
We could also look at either of the two previous solutions and notice that the output of each stage is used as the last argument to the next function in the pipeline. Thus, we could also solve it with thread-last:
(def result3 (->> data
first
:children
(filter #(= (% :a) 1))))
(spyx result3)
;;-> result3 => ({:c 3, :b 2, :a 1} {:c 4, :b 3, :a 1})
Unless your processing chain is very simple, I find it is just about always clearer to use the it-> form to be explicit about how the intermediate value should be used by each stage of the pipeline.
I'm not sure why the first-thread is not applying the filter function, passing in the :children vector as the coll argument.
This is precisely what the thread-first macro does.
From the clojuredocs.org:
Threads the expr through the forms. Inserts x as the
second item in the first form, making a list of it if it is not a
list already.
So, in your case the application of filter ends up being:
(filter [...] #(= (% :a) 1))
If you must use thread-first (instead of thread-last), then you can get around this by partially applying filter and its predicate:
(->
data
first
:children
((partial filter #(= (:a %) 1)))
vec)
; [{:a 1, :b 2, :c 3} {:a 1, :b 3, :c 4}]
I have seen this but can't work out how to apply it (no pun intended) to my situation.
I have a sorted list of maps like this: (note there can be more than two keys in the map)
({name1 3, name2 7}, {name1 35, name2 7}, {name1 0, name2 3})
What I am after is this data structure afterwards:
({:name1 [3,35,0]}, {:name2 [7,7,3]})
Ive been struggling with this for a while and cant seem to get anywhere near.
Caveats: The data must stay sorted and I have N keywords not just two.
I'd go for merge-with with some preprocessing added:
(def maps [{:a :b :e :f} {:a :c} {:a :d :e :g}])
(apply merge-with concat (for [m maps [k v] m] {k [v]}))
>>> {:e (:f :g), :a (:b :c :d)}
I think the function you want is merge-with:
user=> (def x {:a 1 :b 2})
user=> (def y {:a 3 :b 4})
user=> (merge-with vector x y)
{:a [1 3], :b [2 4]}
user=>
user=> (def z {:a 5 :b 6 :c 7})
user=> (merge-with vector x y z)
{:a [[1 3] 5], :c 7, :b [[2 4] 6]} ; oops
user=> (merge-with #(vec (flatten (vector %1 %2))) x y z)
{:a [1 3 5] :b [2 4 6] :c 7}
user=>
This is my attempt at the problem. It is not as elegant as Rafal's solution.
(def maps [{:a :b :e :f} {:a :c} {:a :d :e :g}])
(apply merge-with #(if (list? %1) (conj %1 %2) (list %1 %2)) maps)
>>> {:a (:d :b :c), :e (:f :g)}