我正在寻找的函数必须返回第一个的索引,即一对“”。
例如,使用序列
{“h i,a l l”:3,“h o w,i s”:“x”}
'(#\ {#\“#\ h#\ i#\,#\ a#\ l ......)
该函数应返回11,而不是4(第一次出现逗号),因为它位于“”之间。
我试过这个:
(defun control-comma (x p)
(cond ((eql (car x) #\")
(control-comma (subseq x (+ (position #\" x :start (+ 1 p)) 1)) p))
((eql (car x) #\,)
p)
(t
(control-comma (cdr x) (+ 1 p)))
)
)
使用x作为输入列表,使用p作为0参数来计算位置,但它不起作用,似乎远离我正在寻找的解决方案。
感谢您的每一个建议。
答案 0 :(得分:3)
我建议您使用预定义的position-if
运算符:
(defun first-comma (string start)
(let ((in-double-quote nil))
(position-if
(lambda (x)
(case x
((#\") (progn (setf in-double-quote (not in-double-quote)) nil))
((#\,) (not in-double-quote))))
string
:start start)))
CL-USER> (first-comma (coerce "{ \"hi, all\" : 3, \"how, is\" : \"x\" }" 'list) 0)
15
更复杂的递归解决方案再次基于一次扫描输入列表的想法,由以下函数给出,其中状态“内部双引号”通过几个递归本地函数编码:
(defun fist-comma (x pos)
(labels ((looking-for-comma (x pos)
(cond ((null x) nil)
((eql (car x) #\,) pos)
((eql (car x) #\") (looking-for-double-quote (cdr x) (1+ pos)))
(t (looking-for-comma (cdr x) (1+ pos)))))
(looking-for-double-quote (x pos)
(cond ((null x) nil)
((eql (car x) #\") (looking-for-comma (cdr x) (1+ pos)))
(t (looking-for-double-quote (cdr x) (1+ pos))))))
(looking-for-comma (nthcdr pos x) pos)))
最后,请注意,在上述两个函数中,应考虑使用适当的方法可能转义双引号。