I'm trying to print out my binary tree but Clojure is giving me a hard time printing out the sequences properly.
So, I have a list of nodes '(1 2 3) for example.
In each iteration I want to print out the node with a number of spaces before and after each element.
(defn spaces [n]
(apply str (repeat n " ")))
Great, this seems to work.
So, suppose I have a list of nodes '(:a :b :c) I want to print out on one line, with as said, the spaces.
(println (map #(str (spaces before) % (spaces (dec before))) nodes))
I have a list of items. Using the map I get a list of string objects. Great, so I can print them!
But this gives me this:
(clojure.lang.LazySeq#d0b37c31 clojure.lang.LazySeq#105879a9 clojure.lang.LazySeq#8de18242)
So I googled how to print lazy sequences and I came around to using print-str command. According to the docs this prints to a string which then gets returned.
(println (print-str (map #(str (spaces before) % (spaces (dec before))) nodes)))
But this gives me this:
(clojure.lang.LazySeq#d0b37c31 clojure.lang.LazySeq#105879a9 clojure.lang.LazySeq#8de18242)
No change.. Hrm. Any help is greatly appreciated.
user> (str (map inc (range 10)))
"clojure.lang.LazySeq#c5d38b66"
user> (pr-str (map inc (range 10)))
"(1 2 3 4 5 6 7 8 9 10)"
The toString method of LazySeq is called by str, and this avoids realizing the lazy sequence of values by opaquely showing the Object identity. The pr-str function calls the print-dup multimethod of an object, which is designed to get the version of a thing that could be understood by the reader (so for a LazySeq the literal value that would make an equal LazySeq).
For pretty formatting of structures, do check out the clojure.pprint namespace which comes with clojure.core, which has pprint, print-table, and various functions for customizing the behavior of pretty printing.
user> (require '[clojure.pprint :as pprint :refer [pprint print-table]])
nil
user> (pprint [:a [:b :c :d [:e :f :g] :h :i :j :k] :l :m :n :o :p :q [:r :s :t :u :v] [:w [:x :y :z]]])
[:a
[:b :c :d [:e :f :g] :h :i :j :k]
:l
:m
:n
:o
:p
:q
[:r :s :t :u :v]
[:w [:x :y :z]]]
nil
user> (print-table (map #(let [start (rand-int 1e6)] (zipmap % (range start (+ start 10)))) (repeat 5 [:a :b :c :d :e :f :g :h :i :j])))
| :a | :c | :b | :f | :g | :d | :e | :j | :i | :h |
|--------+--------+--------+--------+--------+--------+--------+--------+--------+--------|
| 311650 | 311652 | 311651 | 311655 | 311656 | 311653 | 311654 | 311659 | 311658 | 311657 |
| 67627 | 67629 | 67628 | 67632 | 67633 | 67630 | 67631 | 67636 | 67635 | 67634 |
| 601726 | 601728 | 601727 | 601731 | 601732 | 601729 | 601730 | 601735 | 601734 | 601733 |
| 384887 | 384889 | 384888 | 384892 | 384893 | 384890 | 384891 | 384896 | 384895 | 384894 |
| 353946 | 353948 | 353947 | 353951 | 353952 | 353949 | 353950 | 353955 | 353954 | 353953 |
nil
Related
In the clojure documentation it says:
Usage: (reduced x)
Wraps x in a way such that a reduce will terminate with the value x
I am trying to return from a reduce function with a boolean and a vector values.
(def bp (reduce (fn [[balanced stack] singlenum]
(def stack2 (conj stack singlenum))
(println stack2)
(if (= 2 singlenum)
(reduced [false stack2])
)
[balanced stack2]
)
[true (vector)] [1 2 3 4]
))
bp evaluates as [true [1 2 3 4]], I was expecting [false [1 2]]. The reduced did not terminate the reduce function. I was attempting to terminate the reduce function with a specific values.
You have the correct logic there. I just revised your usage of if and def.
if - I moved [balanced stack2] to the else part. Otherwise reduced will never be detected.
def - the def inside fn should be replaced with let
(def bp (reduce (fn [[balanced stack] singlenum]
(let [stack2 (conj stack singlenum)]
(println stack2)
(if (= 2 singlenum)
(reduced [false stack2])
[balanced stack2])))
[true (vector)]
[1 2 3 4]))
| | | | | stack=> []
| | | | | singlenum=> 1
| | | | (conj stack singlenum)=> [1]
| | | | stack2=> [1]
[1]
| | | (println stack2)=> nil
| | | | | singlenum=> 1
| | | | (= 2 singlenum)=> false
| | | | | balanced=> true
| | | | | stack2=> [1]
| | | (if (= 2 singlenum) (reduced #) [balanced stack2])=> [true [1]]
| | (let [stack2 #] (println stack2) (if # # #))=> [true [1]]
| | | | | stack=> [1]
| | | | | singlenum=> 2
| | | | (conj stack singlenum)=> [1 2]
| | | | stack2=> [1 2]
[1 2]
| | | (println stack2)=> nil
| | | | | singlenum=> 2
| | | | (= 2 singlenum)=> true
| | | | | | stack2=> [1 2]
| | | | (reduced [false stack2])=> #reduced[{:status :ready, :val [false [1 2]]} 0x5fbdbb78]
| | | (if (= 2 singlenum) (reduced #) [balanced stack2])=> #reduced[{:status :ready, :val [false [1 2]]} 0x5fbdbb78]
| | (let [stack2 #] (println stack2) (if # # #))=> #reduced[{:status :ready, :val [false [1 2]]} 0x5fbdbb78]
(reduce (fn # #) [true #] [1 2 3 4])=> [false [1 2]]
I cannot find build-in functionality in Clojure to filter list of maps by values of keys. For example we have a following list:
user=> (def animals (list {:name "Charlie" :weight 350 :specie :elephant}
{:name "Vasya" :weight 250 :specie :bear}
{:name "John" :weight 200 :specie :elephant}
{:name "Monk" :weight 200 :specie :monkey}))
#'user/animals
And I want to select, for example, all the :specie with value :elephant. How can I do that? The best way I found out is this:
user=> (defn filter-data [data m]
(let [k (keys m) v (vals m)]
(filter #(= (map % k) v) data)))
#'user/filter-data
user=> (clojure.pprint/print-table (filter-data animals {:specie :elephant}))
| :name | :weight | :specie |
|---------+---------+-----------|
| Charlie | 350 | :elephant |
| John | 200 | :elephant |
nil
Is there a better way to do that?
This could easily be achieved with filter
(clojure.pprint/print-table
(filter #(= (:specie %) :elephant) animals))
you can always wrap the filter in a function to get different "syntax", such as:
(defn cool-filter [[k v] l]
(filter #(= (k %) v) l))
(clojure.pprint/print-table
(cool-filter [:specie :elephant] animals))
While the filter solution is obviously the most straight-forward, I'd like to add an alternative in case you need to look up more than one species:
(def grouped-animals (group-by :specie animals))
(:elephant grouped-animals)
; [{:name "Charlie", :weight 350, :specie :elephant} {:name "John", :weight 200, :specie :elephant}]
You can also use function composition:
(filter (comp (partial = :elephant) :specie) animals)
or...
(filter (comp #{:elephant} :specie) animals)
What I have:
Collection (map in this instance, Seqable more generally) of items I want to display in a Markdown table (whichever flavour of Markdown reddit uses).
Sequence of accessor functions that produce the contents of each column of the desired table when mapped over the collection.
Sequence of those column mappings: (for [x accessors] (map x coll))
What I'm trying to do:
Append (repeat "\n") to the sequence of mappings, as the item separator.
apply interleave over the sequence-of-sequences.
Consume the resulting sequence with clojure.string/join to insert the 'table cell separator' "|" and glue it all together.
I just can't seem to get the first step working. All my attempts seem to append the infinite sequence of \n itself rather than that sequence as a single object in a seq of seqs or similar issues. A little help?
Edit: A little input/output example does make sense for something like this so I'd better add it. For simplicity we'll just list numbers and functions of them. Input:
(markdown-table [[[identity] "Number"]
[[(partial * 2)] "Doubled"]] (range 6))
(The strings and such are for making column names - might change that setup later but you can see the accessor functions in there. Just listing the number itself and its doubling.)
For this I have the sequence ((0 1 2 3 4 5) (0 2 4 6 8 10)) and want to end up with the sequence
(0 0 "\n" 1 2 "\n" 2 4 "\n" 3 6 "\n" 4 8 "\n" 5 10 "\n")
Clojure already has something similar to what you are trying to do
(defn markdown-table
[specs xs]
(clojure.pprint/print-table
(for [x xs]
(into {}
(for [{:keys [label fn]} specs] [label (fn x)])))))
(markdown-table [{:label "Number", :fn identity}
{:label "Doubled", :fn (partial * 2)}]
(range 6))
Output (could wrap in with-out-str):
| Number | Doubled |
|--------+---------|
| 0 | 0 |
| 1 | 2 |
| 2 | 4 |
| 3 | 6 |
| 4 | 8 |
| 5 | 10 |
You're looking for interpose
(def items [1 2 3 4 5])
(def accesors [(fn [x] (inc x))
(fn [x] (- 10 x))])
(def mappings (for [x accesors]
(map x items)))
=> ((2 3 4 5 6) (9 8 7 6 5))
(interpose "\n" mappings)
=> ((2 3 4 5 6) "\n" (9 8 7 6 5))
Edit after your sample:
(map (fn [& args]
(apply (juxt identity (partial * 2)) args))
(range 6))
=> ([0 0] [1 2] [2 4] [3 6] [4 8] [5 10])
Then just use interpose on it.
(def accessors [(fn [x] (identity x))
(fn [x] (* x 2))])
(def mappings (map (fn [& args]
(apply (apply juxt accessors) args))
(range 6)))
(interpose "\n" mappings)
=> ([0 0] "\n" [1 2] "\n" [2 4] "\n" [3 6] "\n" [4 8] "\n" [5 10])
While responding I appear to have found a way that works using my original approach. By placing the mapping-sequences in a vector, I can append the \n sequence as one value to interleave rather than as infinitely many values as with concat, cons and so on. The resulting code was
(defn- markdown-table
"Create Markdown for a table displaying a collection
Columns defines the columns to show - give pairs of accessor sequence and display names."
[columns coll]
(let[columns-def (str "|" (clojure.string/join "|" (concat (map second columns)
"\n"
;;All columns are center aligned, for now.
(map (constantly ":--:") columns)))
"\n")
accessors (for [[x _] columns] (apply comp (reverse x))) ;;Reverse so composition is leftmost-first
columns (for [x accessors] (map x coll))
item-separated (conj (vec columns) (repeat "\n"))
cells (apply interleave item-separated)
](clojure.string/join "|" (cons columns-def cells))))
Still not quite sure about the way it handles column definitions but it seems to give the right output.
The first thing I want to say is that I am new to clojure, secondly I want to ask you how to iterate through a map and show all elements in a table? Here is what I have done.
This is my map-
(def kvote(assoc kvote (keyword kljuc){:id id :liga liga :dan dan :cas cas :domaciTim domaciTim :gostujuciTim gostujuciTim :par par :konacanIshod{:1 jedinica :x nerijeseno :2 dvojka}}))
I was using cldwalker table function and did this...
(table [ ["liga" "dan" "cas" "id" "par" "1" "X" "2"] [(:liga(get kvote(keyword :101)))
(:dan(get kvote(keyword :101)))
(:cas(get kvote(keyword :101)))
(:id(get kvote(keyword :101)))
(:par(get kvote(keyword :101)))
(get-in kvote [:101 :konacanIshod :1])
(get-in kvote [:101 :konacanIshod :x])
(get-in kvote [:101 :konacanIshod :2])
]] )
the result is something like this...
+---------+---------+-------+-----+--------------------+-----+-----+---+
| liga | dan | cas | id | par | 1 | X | 2 |
+---------+---------+-------+-----+--------------------+-----+-----+---+
| Serie A | nedelja | 20:00 | 101 | Bologna - Cagliari | 1.5 | 2.3 | 4 |
+---------+---------+-------+-----+--------------------+-----+-----+---+
How can I iterate through the map and show all the elements, not only one by the specific keyword? Can I somehow increment my keyword value and show it like that?
Maps implement the Seq interface, meaning you can use all these useful higher-order functions like map, filter, reduce, ... to process them. The important part here is that the sequential representation of a map consists of [key value] vectors, e.g.:
(seq {:a 0 :b 1})
;; => ([:a 0] [:b 1])
(map (fn [x] (inc (second x))) {:a 0 :b 1})
;; => (1 2)
(If you do not know what map & co. do, read up on them - you will love them (eventually)!)
Now, in your case you're only interested in the values, not the keys, it seems, so vals will retrieve them for you:
(vals {:a 0 :b 1})
;; => (0 1)
(map inc (vals {:a 0 :b 1}))
;; => (1 2)
Your values, however, are maps themselves and you want to access certain keys in said maps and put them into a single vector/list. You can do that!
(map
(fn [x]
[(:key-1 x) (:key-2 x) ...])
(vals your-map-of-maps))
This looks tedious. But creating the inner result is nothing else then looking up each one of a list (!) of keys in a hash map, so another use case for fancy higher-order map:
(map
(fn [x]
(map (fn [k] (k x)) [:key-1 :key-2 ...]))
(vals your-map-of-maps))
Now, actually Clojure makes it really easy to apply different functions (keywords are functions!) to the same value to obtain a list of results - juxt is what it's called, taking a series of functions and producing a new one that does exactly what I just described.
(def inc-and-dec (juxt inc dec))
(inc-and-dec 1)
;; => [2 0]
And here we go for maps:
((juxt :a :b) {:a 0 :b 1 :c 2})
;; => [0 1]
Okay, that's a lot to process but you'll only be able to work efficiently with Clojure if you understand what tools it offers you - and higher-level functions are probably those you'll use the most. Finally, let us create a table:
(table
(cons
["header-1" "header-2" ...]
(map (juxt :key-1 :key-2 ...) (vals your-map-of-maps))))
And now for the grand finale, cleaning up using threading macros!
(->> your-map-of-maps
(map (juxt :key-1 :key-2 ...))
(cons ["header-1" "header-2" ...])
(table))
Yup, there's a lot Clojure can do, and sequences + higher-order-functions are a very powerful combination. And they still solve practical problems like creating a table!
my goal is to print my Table as close with even spaces between each col.
(defn PrintTable [tableName]
"prints table in clear format"
(let [tableRef (get (deref dataBase) tableName) ; get refrence for table
keyList (keys #tableRef)] ; get key list of table
(doseq [tableKeys (range (count keyList))] ; print the keys of the table
(let [key (nth (keys #tableRef) tableKeys)]
(print key "\t|"))
)
(println)
(doseq [rows (range (count #(tableRef (nth (keys #tableRef) 0))))] ; print for each rows all the values
(doseq [cols (range (count keyList))]
(let [key (nth (keys #tableRef) cols)]
(print (#(tableRef key) rows) "\t|")
)
)
(println)
)
)
(println)
)
i have tried using tab however this is the out come i get:
P_Id |LastName |FirstName |Address |City |
1 |Darmon |Gilad |ishayahu |Haifa |
2 |SM |Shiran |erez |RamatIshay |
D_Id |Name |OwnerLastName |OwnerFirstName |
a |Bono |Darmon |Gilad |
b |Bony |SM |Shiran |
any suggestion for a nicer and aligned print?
use format to make the cols line up:
user> (println (format "%20s %20s %20s\n%20s %20s %20s"
"short" "medium" "reallylong"
"reallylong" "medium" "short"))
short medium reallylong
reallylong medium short
nil
user>
or left justify with %-20s
user> (println (format "%-20s %-20s %-20s\n%-20s %-20s %-20s"
"short" "medium" "reallylong"
"reallylong" "medium" "short"))
short medium reallylong
reallylong medium short
nil
user>
This might be helpful:
http://clojuredocs.org/clojure_core/clojure.pprint/print-table
Alpha - subject to change.
Prints a collection of maps in a textual table. Prints table headings
ks, and then a line of output for each row, corresponding to the keys
in ks. If ks are not specified, use the keys of the first item in rows.
(defn print-table [res]
(let [headers (map name (keys (first res)))
table (concat [headers] (map vals res))
trans-table (apply map vector table)
cols-width (map #(apply max (map (comp count str) %))
trans-table)]
(doseq [row table]
(println
(apply format
(str "|" (apply str (str/join "|" (map #(str "%-" % "s")
cols-width)))
"|")
row)))))
(print-table res)
=> |P_Id|LastName|FirstName|Address |City |
|1 |Darmon |Gilad |ishayahu|Haifa |
|2 |SM |Shiran |erez |RamatIshay|
I am used to print-table with with-out-str
user=> (def res [{:P_Id 1 :LastName "Darmon" :FirstName "Gilad"} {:P_Id 2 :LastName "SM" :FirstName "Shiran"}])
#'user/res
user=> (printf "res=%s" (with-out-str (clojure.pprint/print-table res)))
res=
| :P_Id | :LastName | :FirstName |
|-------+-----------+------------|
| 1 | Darmon | Gilad |
| 2 | SM | Shiran |
nil