Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Idiomatic way for finding if an element exists in an nested vector

Tags:

clojure

I have modeled my data as embedded vectors. I need to find if an element exists within these vectors. I have the below code which does it correctly. However, I'd like suggestions on a more idiomatic way to do it.

(defn exists-in-vector?
  [my-vec my-sym]
  (= my-sym (first my-vec)))

(defn exists-in-vectors?
  [all-vectors my-symbol]
  (empty? (for [first-vector all-vectors
               second-vector first-vector
               third-vector second-vector
               :when (exists-in-vector? third-vector my-symbol)
               :while (exists-in-vector? third-vector my-symbol)]
           true)))

> (exists-in-vectors? [[[[:a 20] [:b :30]] [[:c 20] [:d :30]]]
                      [[[:h 20] [:g :30]] [[:f 20] [:e :30]]]]
                      :a) => true
like image 242
murtaza52 Avatar asked Dec 06 '22 08:12

murtaza52


1 Answers

This is one of the few cases where 'flatten' is exactly what you want:

(def vectors [[[[:a 20] [:b :30]] [[:c 20] [:d :30]]] 
             [[[:h 20] [:g :30]] [[:f 20] [:e :30]]]])

(some #{:g} (flatten vectors))
;=> :g

(some #{:k} (flatten vectors))
;=> nil

By the way, the definition of flatten is interesting. (source flatten) or http://clojuredocs.org/clojure_core/clojure.core/flatten :

(defn flatten
  "Takes any nested combination of sequential things (lists, vectors,
  etc.) and returns their contents as a single, flat sequence.
  (flatten nil) returns nil."
  {:added "1.2"
   :static true}
  [x]
  (filter (complement sequential?)
          (rest (tree-seq sequential? seq x))))
like image 71
Chouser Avatar answered Dec 11 '22 11:12

Chouser