How to match a vector to a map by clicking on it with duplicate key values?

This is my input:

[[:a 1 2] [:a 3 4] [:a 5 6] [:b \a \b] [:b \c \d] [:b \e \f]]

I would like to display this in the following:

{:a [[1 2] [3 4] [5 6]] :b [[\a \b] [\c \d] [\e \f]]}

This is what I have so far:

(defn- build-annotation-map [annotation & m]
 (let [gff (first annotation)
       remaining (rest annotation)
       seqname (first gff)
       current {seqname [(nth gff 3) (nth gff 4)]}]
   (if (not (seq remaining))
     m
     (let [new-m (merge-maps current m)]
       (apply build-annotation-map remaining new-m)))))

(defn- merge-maps [m & ms]
  (apply merge-with conj
         (when (first ms)                                                                                                              
           (reduce conj                     ;this is to avoid [1 2 [3 4 ... etc.                                                                                                          
                   (map (fn [k] {k []}) (keys m))))                                                                                    
         m ms))

The above gives:

{:a [[1 2] [[3 4] [5 6]]] :b [[\a \b] [[\c \d] [\e \f]]]}

It seems to me that the problem is merge-maps, in particular, with the function passed to merge-with( conj), but after I hit my head for a moment, I'm ready for someone to help me.

I am new to lisp in general and clojure in particular, so I also appreciate comments that are not related to a specific problem, but also style, brain constructs on my part, etc. Thank!

Solution (close enough):

(group-by first [[:a 1 2] [:a 3 4] [:a 5 6] [:b \a \b] [:b \c \d] [:b \e \f]])
=> {:a [[:a 1 2] [:a 3 4] [:a 5 6]], :b [[:b \a \b] [:b \c \d] [:b \e \f]]}
+3
source share
5 answers
(defn build-annotations [coll]
  (reduce (fn [m [k & vs]]
            (assoc m k (conj (m k []) (vec vs))))
          {} coll))

, . -, , , , annotation, gff seqname. current . Clojure, remaining more, , .

let gff (first annotation) remaining (rest annotation) , , , :

(let [[first & more] annotation] ...)

(rest annotation), next, nil, , (if-not remaining ...), (if-not (seq remaining) ...).

user> (next [])
nil
user> (rest [])
()

Clojure, lisps, .

.

+9

.

(defn build-annotations [coll]
  (reduce
    (fn [result vec]
      (let [key (first vec)
            val (subvec vec 1)
            old-val (get result key [])
            conjoined-val (conj old-val val)]
        (assoc
          result
          key
          conjoined-val)))
    {}
    coll))

(build-annotations [[:a 1 2] [:a 3 4] [:a 5 6] [:b \a \b] [:b \c \d] [:b \e \f]])

, . Clojure, , .

+4

, :

(defn build-annotations [coll]
  (let [anmap (group-by first coll)]
    (zipmap (keys anmap) (map #(vec (map (comp vec rest) %)) (vals anmap)))))
+4

, , , . , :

(defn f [s]
  (let [g (group-by first s)
        k (keys g)
        v (vals g)
        cleaned-v (for [group v]
                    (into [] (map (comp #(into [] %) rest) group)))]
    (zipmap k cleaned-v)))

, , , .

+2
(defn build-annotations [coll]
  (apply merge-with concat 
         (map (fn [[k & vals]] {k [vals]}) 
              coll))

,

(map (fn [[k & vals]] {k [vals]}) 
     coll))

[ ] {key [values]}

(apply merge-with concat ...list of maps...)

, , .

+2

Source: https://habr.com/ru/post/1764356/


All Articles