对多个字符串进行操作以生成一个字符串

Operating on multiple strings to produce a string

result 设置为 ("cypueihajytotrdkgzxfqplbwn" . "cypueihajytomrdkgzxfqplbwn"),下面的代码给出了删除不匹配字符 "t" 的预期结果: "cypueihajytordkgzxfqplbwn"

如果没有 concat,结果将作为整数列表返回,表示字符串中每个字符的 ASCII 值。但是输入本身被评估者视为字符串。所以我在算法中失去了 result 的字符串性(可能是因为 mapcar* 将每个字符串视为字符列表,而字符只是整数)。

我的问题是 - 是否有一种惯用的方法来保持变量的严格性,而不是必须在最后使用 concatapply #'string 重新强制执行它。恕我直言,concat 使代码有点嘈杂(呃)。

(print (concat (mapcar #'car (cl-remove-if-not 
        (lambda (r) (equal (car r) (cdr r)))
        (mapcar* #'cons (car result) (cdr result))))))

Emacs Lisp 中的主要数据类型是列表。 Emacs 提供了很多函数(如carcdr)来处理列表,列表比数组(包括向量和字符串)更容易处理。例如,函数 mapcar returns 即使您将字符串或向量传递给它也是一个列表:

(mapcar #'identity "hello")
;; => (104 101 108 108 111)

(mapcar #'identity [1 2 3])
;; => (1 2 3)

将数组转换为列表、处理列表,然后再转换回数组的情况并不少见。除了 concatstring,您还可以使用 mapconcat.

构建字符串

对于你的代码,你使用了3次类似mapcar的函数,下面只使用了一次,我觉得这样更容易阅读

(let ((result (cons "cypueihajytotrdkgzxfqplbwn"
                    "cypueihajytomrdkgzxfqplbwn")))
  (concat
   (delq
    nil
    (cl-mapcar
     (lambda (c1 c2) (and (= c1 c2) c1))
     (car result) (cdr result)))))
;; => "cypueihajytordkgzxfqplbwn"

使用命令式方法,代码更加简洁

(let ((result (cons "cypueihajytotrdkgzxfqplbwn"
                    "cypueihajytomrdkgzxfqplbwn")))
  (cl-loop for x across (car result)
           for y across (cdr result)
           when (= x y)
           concat (string x)))
;; => "cypueihajytordkgzxfqplbwn"