列表差异功能

时间:2013-05-08 04:17:48

标签: list functional-programming lisp ml

任何现有的编程语言,特别是在Lisp或ML系列中,是否具有库函数来计算“从第一个开始到第二个开始”意义上的列表差异 - 我不确定它应该被称为究竟是什么 - 例如,如果输入为:

,则将字符串视为字符列表
abcdef
def

然后输出

abc

3 个答案:

答案 0 :(得分:3)

Common Lisp中的代码:

CL-USER 1 > (defun fusos (s1 s2)
              (let ((pos (search s2 s1)))
                (when pos (subseq s1 0 pos))))
FUSOS

CL-USER 2 > (fusos '(a b c d e f) '(d e f))
(A B C)

答案 1 :(得分:3)

已经有一个已接受的答案,但Common Lisp的LDIFF(“列表差异”的缩写)仍然值得一提。它基于列表的结构(列表构成的缺点单元格)而不是列表的元素,因此“减去”的列表必须是与某些尾部相同的相同的缺点单元格的清单。它有点具体,但它肯定会计算列表差异。

CL-USER> (let* ((abcdef '(a b c d e f))
                (def (cdddr abcdef)))
           (ldiff abcdef def))
(A B C)

答案 2 :(得分:1)

由于注释中提到takeWhile并且Haskell具有此函数,因此以下是在Haskell中实现所需结果的方法:

takeWhile (flip notElem ys) xs

你的例子是

takeWhile (flip notElem "def") "abcdef"

即,您可以从列表xs中获取元素,只要它们不包含在列表ys中即可。一旦找到ys中包含的元素(或点击xs的末尾),就会停止。

在标准ML中,它将是:

fun take_while p [] = []
  | take_while p (x::xs) =
    if p x then x :: take_while p xs
    else []

编辑:上面,我认为规范是我们在第一个列表中停止,只要我们找到第二个列表中的(任意)元素。因此使用takeWhile。但是,从OP来看,我不清楚实际的规格是什么。如果从输入(第一个列表)中删除现有后缀(第二个列表),那么解决方案当然是不同的。在Haskell,没有考虑效率,我们可以这样做:

removeSuffix [] ys = []
removeSuffix xs@(z:zs) ys
  | xs == ys = []
  | otherwise = z : removeSuffix zs ys