我有一个正在开发的天气预报应用程序,但我在使用关联列表时遇到了一些麻烦。我使用 openweathermap 和 convert-to-json 从我的 get-weather 函数返回了以下列表:
((:COORD (:LON . -123.12) (:LAT . 49.25))
(:WEATHER
((:ID . 500) (:MAIN . "Rain") (:DESCRIPTION . "light rain") (:ICON . "10n")))
(:BASE . "cmc stations")
(:MAIN (:TEMP . 281.56) (:PRESSURE . 1001) (:HUMIDITY . 93)
(:TEMP--MIN . 276.15) (:TEMP--MAX . 283.15))
(:WIND (:SPEED . 3.1) (:DEG . 100)) (:CLOUDS (:ALL . 90)) (:DT . 1453467600)
(:SYS (:TYPE . 1) (:ID . 3359) (:MESSAGE . 0.0039) (:COUNTRY . "CA")
(:SUNRISE . 1453478139) (:SUNSET . 1453510389))
(:ID . 6173331) (:NAME . "Vancouver") (:COD . 200))
我正在尝试访问 :weather :main rain。目前我在做:
(cdr (second (second (assoc :weather *assoc-list-from-above*))))
有没有更好的办法?
最佳答案
虽然我非常喜欢@jkiiski 的json-bind
解决方案,但我想我也应该添加以下选项。
如果查询路径在编译时已知,您可以使用下面的宏
(defmacro report-get (report &optional key &rest keys)
(cond
((null key) report)
((integerp key) `(report-get (nth ,key ,report) ,@keys))
(t `(report-get (cdr (assoc ,key ,report)) ,@keys))))
例子:
CL-USER> (report-get *array-from-above* :weather 0 :main)
"Rain"
CL-USER> (report-get *array-from-above* :coord :lon)
-123.12
CL-USER> (macroexpand '(report-get *array-from-above* :weather 0 :main))
(CDR (ASSOC :MAIN (NTH 0 (CDR (ASSOC :WEATHER *ARRAY-FROM-ABOVE*)))))
T
(report-get *array-from-above* :weather 0 :main)
中的 0
是访问天气项目集合中的第一项
编辑:忘记提及 - 这个宏是setf
-able。
CL-USER> (report-get *array-from-above* :weather 0 :main)
"Rain"
CL-USER> (setf (report-get *array-from-above* :weather 0 :main) "Sunny")
"Sunny"
CL-USER> (report-get *array-from-above* :weather 0 :main)
"Sunny"
可能对您的要求没有用,但很高兴知道。
关于lisp - 在 Common Lisp 中访问 Assoc 列表的更好方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34948131/