You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改键为字符串的嵌套plist并生成值修改后的等同新变量

解决方案

1. 直接修改原plist

嵌套使用getf定位到目标值后直接赋值即可,getf本身支持setf修改对应位置的值:

(setf (getf (getf (getf response "person") "child-1") "grandchild-1b")
      "grandchild-1b-value-modified")
;; 操作完成后可直接返回response
response

该方案会直接修改解析得到的response对象,不需要额外拷贝开销。

2. 生成新plist不修改原对象

推荐直接对原plist做深拷贝后修改副本,Common Lisp生态常用的Alexandria工具库提供了开箱即用的copy-tree函数实现深拷贝:

(let ((modified-response (alexandria:copy-tree response)))
  (setf (getf (getf (getf modified-response "person") "child-1") "grandchild-1b")
        "grandchild-1b-value-modified")
  ;; 返回修改后的新plist,原response完全不受影响
  modified-response)

如果不想引入第三方依赖,也可以逐层复制需要修改的plist层级,仅修改目标路径的结构,其余部分和原对象共享内存,性能更高:

(let* ((root-person (getf response "person"))
       (child-1 (getf root-person "child-1"))
       ;; 复制孙层级并替换目标键值
       (new-child-1 (loop for (k v) on child-1 by #'cddr
                          if (string= k "grandchild-1b")
                            collect k and collect "grandchild-1b-value-modified"
                          else
                            collect k and collect v))
       ;; 复制子层级并替换child-1的值
       (new-root-person (loop for (k v) on root-person by #'cddr
                              if (string= k "child-1")
                                collect k and collect new-child-1
                              else
                                collect k and collect v))
       ;; 复制顶层plist并替换person的值
       (new-response (loop for (k v) on response by #'cddr
                           if (string= k "person")
                             collect k and collect new-root-person
                           else
                             collect k and collect v)))
  new-response)

填写到示例代码的最终效果(直接修改原对象版本)

(let ((stream (drakma:http-request endpoint
                                   :method :post
                                   :want-stream t
                                   :content-type "application/json"
                                   :content request)))
  (setf (flexi-streams:flexi-stream-external-format stream) :utf-8)
  (let ((response (yason:parse stream :object-as :plist)))
    (setf (getf (getf (getf response "person") "child-1") "grandchild-1b")
          "grandchild-1b-value-modified")
    response))

内容的提问来源于stack exchange,提问作者user3735178

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.16 22:06:03