我有两个长度相同的字符串,它们只有一个字符不同,我想要一个所有字符都相等的字符串。所以基本上是这样的,它的计算结果是一个字符串而不是字符列表:
(loop for a across "abcd"
for b across "abce"
when (char= a b) collect a)
虽然性能在这里不是问题,但我发现周围有
(coerce ... 'string)
很麻烦。
所以我想出了类似的东西
(loop with result = ""
for a across "abcd"
for b across "abce"
when (char= a b)
do (setf result (concatenate 'string result (string a)))
finally (return result))
它可以完成工作,但对我来说看起来不太优雅。
(map 'string (lambda (a b) (when (char= a b) a)) "abcd" "abce")
看起来更好,但不起作用,因为当
NIL
和 a
不相等时,b
不是一个字符。
是否有更优雅的习惯用法来迭代字符串并返回字符串?
(loop with result = ""
for a across "abcd"
for b across "abce"
when (char= a b)
do (setf result (concatenate 'string result (string a)))
finally (return result))
对于较长的字符串,重复连接并不是一个好主意。
替代方案:
循环进入列表并强制转换为字符串
CL-USER 3 > (loop for a across "abcd"
and b across "abce"
when (char= a b) collect a into list
finally (return (coerce list 'string)))
"abc"
使用流并将其转换为字符串
CL-USER 4 > (with-output-to-string (*standard-output*)
(loop for a across "abcd"
and b across "abce"
when (char= a b) do (write-char a)))
"abc"
使用可调节弦
CL-USER 5 > (loop with string = (make-array 0
:element-type 'character
:adjustable t
:fill-pointer 0)
for a across "abcd"
for b across "abce"
when (char= a b) do (vector-push-extend a string)
finally (return string))
"abc"
另一种可能性是使用
mismatch
,如 David Hodge 的评论中所示:
CL-USER> (defun f(a b)
(let ((pos (mismatch a b)))
(concatenate 'string (subseq a 0 pos) (subseq a (1+ pos)))))
F
CL-USER> (f "abcdefg" "abcxefg")
"abcefg"
使用
map
同时循环多个列表
(map 'string #'(lambda (a b) (if (char= a b) a #\Rubout)) "abce" "abcd")
'string
将结果列表强制转换为字符串。 #\Rubout
get 被强制转换为零长度字符串。 #\Backspace
甚至会删除最后一个字符。
另一种方式(它不假设任何有关元素位置的信息)
(defun only-matching (seq1 seq2)
(remove-if-not (lambda (c) (find c seq1)) seq2))
CL-USER> (only-matching "abcd" "abce")
"abc"
CL-USER> (only-matching "abdc" "abec")
"abc"`
或
(coerce
(intersection (coerce "abdc" 'list)
(coerce "abec" 'list))
'string)
这也不保持秩序
注意:remove-if-not 已“正式”弃用。
loop
替换库允许您在其 collect
版本中指定类型来指定返回的内容,而不是默认列表:
CL-USER> (iter
(for a in-string "abcd")
(for b in-string "abce")
(when (char= a b)
(collect a result-type string)))
"abc"
另请注意,它有一个专门用于字符串的迭代形式 (
in-string
),尽管通用向量形式 (in-vector
) 也可以工作。