gpt4 book ai didi

common-lisp - Common Lisp 嵌套结构变化

转载 作者:行者123 更新时间:2023-12-04 03:02:21 28 4
gpt4 key购买 nike

我目前正在学习 Common Lisp,并尝试将一些 JSON 发送到网络服务。我要发送的 JSON 以类似于以下的结构表示:

((:ITEMS
((:KEY . "value1") (:IGNORE 1 2 3))
((:KEY . "value2") (:IGNORE 1 2 3))))

我想从 :ITEMS 中的每个项目中删除 key :IGNORE

在 Clojure(我更熟悉)中,我会使用 update 对键 :ITEMS 应用功能更改,映射每个项目,然后使用 select-keysdissoc 来获取我需要的结构。然而,我无法找到在 Common Lisp 中执行此修改的正确方法。

我是否应该使用 copy-tree 复制结构,然后使用 setf 更改树?

NB1:我不确定我使用的数据结构是否“好”,但它是我调用 json:decode-json-from-string 从CL-Json包。

到目前为止我有这个

(SETF (CDR (ASSOC :ITEMS JSON))
(REMOVE-IF (LAMBDA (E) (EQUAL (CAR E) :IGNORE)) (CDR (ASSOC :ITEMS JSON))))

这是错误的(E 是一个形式为 ((:KEY . "value1") (:IGNORE 1 2 3))) 的列表,但我可以'不知道如何使我的代码正确。

NB2:这就是我在 Clojure 中的做法:

(update json :items #(map (fn [x] (dissoc x :ignore)) %))

最佳答案

其他答案已经显示了使用列表执行此操作的方法,但您也可以自定义 json 解码器以返回更方便的数据结构。由于您想功能性/持久地使用它们,FSet图书馆可能是一个不错的选择。

(ql:quickload '(cl-json :fset :alexandria))
(use-package :alexandria)

首先,让我们自定义解码器,将 json 对象转换为 FSET:MAP,将 json 数组转换为 FSET:SEQ

(defvar *current-array* nil)
(defun beginning-of-array ()
(setf *current-array* (fset:empty-seq)))
(defun array-member (item)
(fset:push-last *current-array* item))
(defun end-of-array ()
*current-array*)

(defvar *current-object* nil)
(defvar *current-object-key* nil)
(defun beginning-of-object ()
(setf *current-object* (fset:empty-map)))
(defun object-key (key)
(setf *current-object-key*
(funcall json:*identifier-name-to-key*
(funcall json:*json-identifier-name-to-lisp* key))))
(defun object-value (value)
(fset:includef *current-object* *current-object-key* value))
(defun end-of-object ()
*current-object*)

(defun call-with-fset-decoder-semantics (function)
(let ((json:*aggregate-scope-variables*
(list* '*current-array* '*current-object* '*current-object-key*
json:*aggregate-scope-variables*)))
(json:bind-custom-vars (:beginning-of-array #'beginning-of-array
:array-member #'array-member
:end-of-array #'end-of-array
:beginning-of-object #'beginning-of-object
:object-key #'object-key
:object-value #'object-value
:end-of-object #'end-of-object)
(funcall function))))

(defmacro with-fset-decoder-semantics (&body body)
`(call-with-fset-decoder-semantics (lambda () ,@body)))

假设您的 JSON 看起来像这样。

(defvar *json* "{
\"something\": \"foo\",
\"items\": [
{
\"key\": \"value1\",
\"ignore\": [1, 2, 3]
},
{
\"key\": \"value2\",
\"ignore\": [1, 2, 3]
}
],
\"other\": \"bar\"
}")

现在您可以将其解码为 FSet 结构。请注意,FSet 使用其自定义阅读器语法来打印对象。 #{| (key value)* |} 表示 FSET:MAP#[ ... ]FSET:SEQ。如果您希望能够读取它们,您可以使用 FSET:FSET-SETUP-READTABLE,但这不是必需的。在执行此操作之前,您应该创建一个自定义可读表。

(with-fset-decoder-semantics
(json:decode-json-from-string *json*))
;=> #{|
; (:ITEMS
; #[
; #{| (:KEY "value1") (:IGNORE #[ 1 2 3 ]) |}
; #{| (:KEY "value2") (:IGNORE #[ 1 2 3 ]) |} ])
; (:OTHER "bar")
; (:SOMETHING "foo") |}

您可以使用 FSET:IMAGE 从带有 FSET:LESS 的项目中删除 :IGNORE 键。 FSET:WITH 向 map 添加一个键,或替换现有键。

(let ((data (with-fset-decoder-semantics
(json:decode-json-from-string *json*))))
(fset:with data :items (fset:image (rcurry #'fset:less :ignore)
(fset:lookup data :items))))
;=> #{|
; (:ITEMS #[ #{| (:KEY "value1") |} #{| (:KEY "value2") |} ])
; (:OTHER "bar")
; (:SOMETHING "foo") |}

FSet 还可以方便地处理修改宏:

(let ((data (with-fset-decoder-semantics
(json:decode-json-from-string *json*))))
(fset:imagef (fset:lookup data :items) (rcurry #'fset:less :ignore))
data)
;=> #{|
; (:ITEMS #[ #{| (:KEY "value1") |} #{| (:KEY "value2") |} ])
; (:OTHER "bar")
; (:SOMETHING "foo") |}

乍一看,这似乎是在破坏性地修改数据,但实际上并非如此。

(let* ((data (with-fset-decoder-semantics
(json:decode-json-from-string *json*)))
(old-data data))
(fset:imagef (fset:lookup data :items) (rcurry #'fset:less :ignore))
(values data old-data))
;=> #{|
; (:ITEMS #[ #{| (:KEY "value1") |} #{| (:KEY "value2") |} ])
; (:OTHER "bar")
; (:SOMETHING "foo") |}
;=> #{|
; (:ITEMS
; #[
; #{| (:KEY "value1") (:IGNORE #[ 1 2 3 ]) |}
; #{| (:KEY "value2") (:IGNORE #[ 1 2 3 ]) |} ])
; (:OTHER "bar")
; (:SOMETHING "foo") |}

关于common-lisp - Common Lisp 嵌套结构变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46185592/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com