Fork me on GitHub
#beginners
<
2023-07-08
>
joakimen01:07:42

Any tips on how to improve (cleanliness, readability) this code, to drop all the :b-keys? In particular the map-form. Initially tried a combination of update-in and dissoc to drop all the :b-keys, but couldn't get it working since the key is different for each seq-element (`:a`, :b, ..)

(let [m {:a {:a 1 :b 1}
          :b {:a 2 :b 2}
          :c {:a 3 :b 3}
          :d {:a 4 :b 4}}]
   (->> (seq m)
        (map (fn [x] {(first x) (select-keys (second x) [:a])}))
        (into {})))

;; goal:
;; {:a {:a 1}
;;  :b {:a 2}
;;  :c {:a 3}
;;  :d {:a 4}}

Bob B01:07:58

if you're on 1.11+, an option would be update-vals and dissoc :b or call :a or whatever

joakimen09:07:57

Precisely what I was looking for, thanks a lot 😄

(update-vals m #(dissoc % :b))

👍 2
💡 2
AJ Snow23:07:08

hi everyone, what's the least painful way to insert a value into a vector at an arbitrary index? e.g.

(def example [1 2 3 4 5])
(def example-after-insert (insert-value "foo" 7 example)) ; => [1 2 3 4 5 nil nil "foo"] 

AJ Snow23:07:43

If this is something I need to write myself, I'm thinking of using subvec, but I have to imagine this problem has come up before so I'm curious if there are established solutions.

hiredman23:07:17

There is no non-painful way to do it, because vectors as a data structures don't really support it

hiredman23:07:38

You can update existing indices using assoc

leifericf23:07:46

Maybe by using https://clojuredocs.org/clojure.core/assoc? (assoc vector index val)

hiredman23:07:04

The best thing to do is to not use a vector if you need something like that

AJ Snow23:07:36

assoc gives out of bounds if I want to add a value outside the size of the vec to be clear, i'm fine with using any data structure. whatever works best for this sort of problem. I thought about using a map where the key is the index, e.g. {:7 "foo"} but as far as I can tell clojure doesn't like that unless you make it a string, but I can do that instead if that's the better route.

hiredman23:07:19

Just use the number 7

hiredman23:07:46

: indicates a keyword, and while you can construct the keyword :7, there is no reason to

hiredman23:07:03

{7 "foo"} is fine

AJ Snow23:07:42

that's the first thing I tried but then indexing doesn't work example attached

AJ Snow23:07:49

oh it works if i do it the reverse way, never knew that

AJ Snow23:07:14

I think i can work with this. i'll do some more testing and then post an update if it works

pavlosmelissinos23:07:26

The reason you can do (:foo m), (m :foo) and (m 7), where m is a map, is because maps and keywords implement IFn. Numbers don't. You can also use get: (get {7 "foo"} 7) In other words, implementing IFn allows stuff to be placed first inside a pair of parentheses.

AJ Snow23:07:18

that's pretty cool. I think I've heard of that before but never internalized it. and I can't believe I forgot about get , that would also solve this problem. thanks!

pavlosmelissinos00:07:47

Don't worry, it takes time 🙂

AJ Snow00:07:13

Problem: I need a data structure that allows me to add values at arbitrary indexes to access later, the indexes specifically need to be numbers. Solution: Use a map, it should probably work depending on your use case. You don't have to index via traditional keywords, but you should look at the docs to see how not-trad keywords, like numbers or strings, work. for example normally (:x {:x "foo"}) works fine but won't work if it's (7 {7 "foo"}) instead you have to do either ({7 "foo"} 7) or (get {7 "foo"} 7) And thanks to everyone who offered input in the thread. doc: https://clojure.org/guides/learn/hashed_colls

Ben Sless04:07:22

If you want to keep a notion of order use an ordered map?

👍 2
AJ Snow00:07:13

Problem: I need a data structure that allows me to add values at arbitrary indexes to access later, the indexes specifically need to be numbers. Solution: Use a map, it should probably work depending on your use case. You don't have to index via traditional keywords, but you should look at the docs to see how not-trad keywords, like numbers or strings, work. for example normally (:x {:x "foo"}) works fine but won't work if it's (7 {7 "foo"}) instead you have to do either ({7 "foo"} 7) or (get {7 "foo"} 7) And thanks to everyone who offered input in the thread. doc: https://clojure.org/guides/learn/hashed_colls