我想知道是否可以将类似Regex的模式匹配应用于plist中的键。
也就是说,假设我们有一个像(:input1 1 :input2 2 :input3 3 :output1 10 :output2 20 ... :expand "string here")
我需要编写的代码类似于:
“如果列表的键中有:expand
和(:input*
或:output*
),那么请执行操作并返回:expand
和(:output*
或:input*
)“。
显然,这可以通过cond
完成,但我没有看到一个明确的方式来优雅地写这个。因此,我想到可能在键上使用类似Regex的模式,并根据模式搜索的结果返回。
任何建议都表示赞赏。
答案 0 :(得分:4)
算法的第一步可以简化问题的其余部分,即以一种以结构化方式保留相同信息的方式规范化输入,而不是在符号内部。我正在将符号转换为符号或列表。您还可以定义自己的类,它表示输入和输出,并编写适用于两者的通用函数。
(defun normalize-key (key)
(or (cl-ppcre:register-groups-bind (symbol number)
("^(\\w+)(\\d+)$" (symbol-name key))
(list (intern symbol "KEYWORD")
(parse-integer number)))
key))
(defun test-normalize ()
(assert (eq (normalize-key :expand) :expand))
(assert (equal (normalize-key :input1) '(:input 1))))
以上normalize-key
将:inputN
解构为(:input N)
列表,N
解析为数字。使用上面的函数,您可以规范化整个列表(如果需要,您也可以递归地对值进行操作):
(defun normalize-plist (plist)
(loop
for (key value) on plist by #'cddr
collect (normalize-key key)
collect value))
(normalize-plist
'(:input1 1 :input2 2 :input3 3 :output1 10 :output2 20 :expand "string here"))
=> ((:INPUT 1) 1
(:INPUT 2) 2
(:INPUT 3) 3
(:OUTPUT 1) 10
(:OUTPUT 2) 20
:EXPAND "string here")
从那里,您应该能够更轻松地实现您的逻辑。