sketchmabaso
sketchmabaso

Reputation: 21

Clojure: Is there a way to remove a key but keep its values

I need some help with a pickle. I have the below map

    (def my-list 
{:data-0
  {:a1 ;;this is the value for :ward-room
            {:type "Specialist"
            :name "Dr Spongebob"
            :illness "dehydration"
            :ward-room "a1"}}
:data-1
  {:b5
      {:type "GP"
        :name "Dr Patrick"
        :illness "fishy eyes"}
        :ward-room "b5"}})

I want to transform this into a map such as below

(def my-new-list 
{:data-0
            {:type "Specialist"
            :name "Dr Spongebob"
            :illness "dehydration"
            :ward-room "a1"}
:data-1
      {:type "GP"
        :name "Dr Patrick"
        :illness "fishy eyes"}
        :ward-room "b5"}})

I couldn't figure out how to do this so I've tried using seq and then flatten but have not had success. Im not too sure how to get started Solving this problem. I would really appreciate a little help

Upvotes: 1

Views: 184

Answers (3)

If my-list is supposed to be defined as

(def my-list 
  {:data-0
     {:a1 ;;this is the value for :ward-room
       {:type "Specialist"
        :name "Dr Spongebob"
        :illness "dehydration"
        :ward-room "a1"}}
   :data-1
     {:b5
       {:type "GP"
        :name "Dr Patrick"
        :illness "fishy eyes"
        :ward-room "b5"}}})

(that is, if we include the :ward-room key and value in the :b5 map rather than having it floating around on the loose) then the quickest way I can see to do this is:

(zipmap (keys my-list) (map #(first (vals %)) (vals my-list)))

It we wrap the above in a (pprint...) form it returns

{:data-0
 {:type "Specialist",
  :name "Dr Spongebob",
  :illness "dehydration",
  :ward-room "a1"},
 :data-1
 {:type "GP",
  :name "Dr Patrick",
  :illness "fishy eyes",
  :ward-room "b5"}}

EDIT

Or if you prefer it in thread-last form you can use

(->> my-list
  (vals)
  (map #(first (vals %)))
  (zipmap (keys my-list)))

Upvotes: 2

Alan Thompson
Alan Thompson

Reputation: 29984

I think your data sample had a cut/paste error. Here is a simple answer:

(def my-data
  {:data-0 {:a1 {:type      "Specialist"
                 :name      "Dr Spongebob"
                 :illness   "dehydration"
                 :ward-room "a1"}}
   :data-1 {:b5 {:type      "GP"
                 :name      "Dr Patrick"
                 :illness   "fishy eyes"
                 :ward-room "b5"
                 }}})

(defn delete-intermediate-level
  [data]
  (into {}
    (for [[k1 v1] data]
      [k1 (into {}
            (for [[k2 v2] v1]
              v2))])))

with result:

(delete-intermediate-level my-data) => 
    {:data-0
     {:type "Specialist",
      :name "Dr Spongebob",
      :illness "dehydration",
      :ward-room "a1"},
     :data-1
     {:type "GP",
      :name "Dr Patrick",
      :illness "fishy eyes",
      :ward-room "b5"}}

Upvotes: 2

leetwinski
leetwinski

Reputation: 17849

considering corrected structure, with :ward-room having the same nesting level for both entries:

(def my-list 
  {:data-0
   {:a1 ;;this is the value for :ward-room
    {:type "Specialist"
     :name "Dr Spongebob"
     :illness "dehydration"
     :ward-room "a1"}}
   :data-1
   {:b5
    {:type "GP"
     :name "Dr Patrick"
     :illness "fishy eyes"
     :ward-room "b5"}}})

there are some options:

first of all you could use reduce-kv, remapping to new vals:

(reduce-kv
 (fn [acc k v] (assoc acc k (val (first v))))
 {}
 my-list)

;; {:data-0
;; {:type "Specialist",
;;  :name "Dr Spongebob",
;;  :illness "dehydration",
;;  :ward-room "a1"},
;; :data-1
;; {:type "GP",
;;  :name "Dr Patrick",
;;  :illness "fishy eyes",
;;  :ward-room "b5"}}

or you could use zipmap to zip keys with new vals:

(zipmap (keys my-list)
        (map (comp val first val) my-list))

also there is a nice way to do it with functional composition:

(into {} (map (juxt key (comp val first val))) my-list)

Another approach is to splice the entries for every internal map at the upper level. This would also work for 'malformed' data, like yours:

(def my-list 
  {:data-0
   {:a1 ;;this is the value for :ward-room
    {:type "Specialist"
     :name "Dr Spongebob"
     :illness "dehydration"
     :ward-room "a1"}}
   :data-1
   {:b5
    {:type "GP"
     :name "Dr Patrick"
     :illness "fishy eyes"}
    :ward-room "b5"}})


(defn lift-entries [old-entries]
  (into {} (mapcat #(if (map? (val %))
                      (val %)
                      [%]))
        old-entries))

(zipmap (keys my-list) (map lift-entries (vals my-list)))

;; {:data-0
;;  {:type "Specialist",
;;   :name "Dr Spongebob",
;;   :illness "dehydration",
;;   :ward-room "a1"},
;;  :data-1
;;  {:type "GP",
;;   :name "Dr Patrick",
;;   :illness "fishy eyes",
;;   :ward-room "b5"}}

Upvotes: 2

Related Questions