Reputation: 21
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
Reputation: 50077
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"}}
Or if you prefer it in thread-last form you can use
(->> my-list
(vals)
(map #(first (vals %)))
(zipmap (keys my-list)))
Upvotes: 2
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
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