Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clojure - get data inside vector of vectors

I have a vector of vectors that contains some strings and ints:

(def data [
["a" "title" "b" 1]
["c" "title" "d" 1]
["e" "title" "f" 2]
["g" "title" "h" 1]
])

I'm trying to iterate through the vector and return(?) any rows that contain a certain string e.g. "a". I tried implementing things like this:

(defn get-row [data]
  (for [d [data]
        :when (= (get-in d[0]) "a")] d
  ))

I'm quite new to Clojure, but I believe this is saying: For every element (vector) in 'data', if that vector contains "a", return it?

I know get-in needs 2 parameters, that part is where I'm unsure of what to do.

I have looked at answers like this and this but I don't really understand how they work. From what I can gather they're converting the vector to a map and doing the operations on that instead?

like image 993
Touchdown Avatar asked Sep 01 '26 22:09

Touchdown


2 Answers

(filter #(some #{"a"} %) data)

It's a bit strange seeing the set #{"a"} but it works as a predicate function for some. Adding more entries to the set would be like a logical OR for it, i.e.

(filter #(some #{"a" "c"} %) data)
=> (["a" "title" "b" 1] ["c" "title" "d" 1])
like image 73
shmish111 Avatar answered Sep 05 '26 04:09

shmish111


ok you have error in your code

(defn get-row [data]
  (for [d [data]
        :when (= (get-in d[0]) "a")] d
  ))

the error is here: (for [d [data] ... to traverse all the elements you shouldn't enclose data in brackets, because this syntax is for creating vectors. Here you are trying to traverse a vector of one element. that is how it look like for clojure:

    (for [d [[["a" "title" "b" 1]
              ["c" "title" "d" 1]
              ["e" "title" "f" 2]
              ["g" "title" "h" 1]]] ...

so, correct variant is:

(defn get-row [data]
  (for [d data
        :when (= "a" (get-in d [0]))]
    d))

then, you could use clojure' destructuring for that:

(defn get-row [data]
  (for [[f & _ :as d] data
        :when (= f "a")]
    d))

but more clojuric way is to use higher order functions:

(defn get-row [data]
  (filter #(= (first %) "a") data))

that is about your code. But corretc variant is in other guys' answers, because here you are checking just first item.

like image 24
leetwinski Avatar answered Sep 05 '26 02:09

leetwinski



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!