Saurabh Jain
Saurabh Jain

Reputation: 1287

How to access LazySeq values

I am playing with wit/duckling library. It has been written in clojure and I have no previous experience in clojure. By following its documentation I got value of a variable as

({:dim :time, :body "20 minutes from now", :value {:type "value", :value "2016-08-03T10:50:56.000+05:30", :grain :second, :values ({:type "value", :value "2016-08-03T10:50:56.000+05:30", :grain :second})}, :start 21, :end 40})

After doing some google search I came to know that it is clojure.lang.LazySeq and tokens starting with colon(:) are keywords instead of keys. I want to access value of :values keyword, I read about clojure basics too but not able to access value of :values keyword. I expect there must be a way so that by writing lazy_seq[:values], I get its value. Can anybody help??

Upvotes: 3

Views: 1511

Answers (2)

Alan Thompson
Alan Thompson

Reputation: 29958

Try this:

> (use 'clojure.pprint)

> (def stuff '({:dim :time, :body "20 minutes from now", :value {:type "value", :value "2016-08-03T10:50:56.000+05:30", :grain :second, :values ({:type "value", :value "2016-08-03T10:50:56.000+05:30", :grain :second})}, :start 21, :end 40}))

We use the "pretty print" function pprint to get a nicely-nested output for the data structure:

> (pprint stuff)
({:dim :time,
  :body "20 minutes from now",
  :value
  {:type "value",
   :value "2016-08-03T10:50:56.000+05:30",
   :grain :second,
   :values
   ({:type "value",
     :value "2016-08-03T10:50:56.000+05:30",
     :grain :second})},
  :start 21,
  :end 40})

So we have a list of one item, which is map of keys :dim :body :value :start and :end. The value for the :value key is another map of keys :type, :value, :grain, :values.

So, to un-nest this,

(pprint (first stuff))
{:dim :time,
 :body "20 minutes from now",
 :value
 {:type "value",
  :value "2016-08-03T10:50:56.000+05:30",
  :grain :second,
  :values
  ({:type "value",
    :value "2016-08-03T10:50:56.000+05:30",
    :grain :second})},
 :start 21,
 :end 40}

> (pprint (:value (first stuff)))
{:type "value",
 :value "2016-08-03T10:50:56.000+05:30",
 :grain :second,
 :values
 ({:type "value",
   :value "2016-08-03T10:50:56.000+05:30",
   :grain :second})}

> (pprint (:values (:value (first stuff))))
({:type "value",
  :value "2016-08-03T10:50:56.000+05:30",
  :grain :second})

You could also use the thread-first macro -> as follows:

> (pprint (-> stuff first :value :values))
({:type "value",
  :value "2016-08-03T10:50:56.000+05:30",
  :grain :second})

so that the original nested structure stuff flows through the functions first, :value, and :values (in that order).

Upvotes: 5

Yuri Steinschreiber
Yuri Steinschreiber

Reputation: 2698

Assuming your sequence is denoted by s:

(get-in (first s) [:value :values])

If there may be multiple elements of the same shape in the sequence, and you want to process all of them at once getting all :values, then

(map #(get-in % [:value :values]) s)

(You don't need to care about laziness.)

Upvotes: 3

Related Questions