Reputation: 1063
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?
Upvotes: 0
Views: 174
Reputation: 6073
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!
Upvotes: 3