【问题标题】:List difference function列表差异函数
【发布时间】:2013-05-02 04:54:29
【问题描述】:

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

abcdef
def

那么输出将是

abc

【问题讨论】:

  • 如果args是abcdefdgf应该有什么输出?
  • 你能举出更多例子吗?

标签: list functional-programming lisp ml


【解决方案1】:

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)

【讨论】:

  • 对,这是实现它的好方法——我猜它没有任何标准名称? take-upto呢?
  • 这种函数有一个标准名称——take-while(它接受一个谓词)。它在不同的 FP 语言中可能有不同的名称
【解决方案2】:

已经有一个公认的答案,但 Common Lisp 的 LDIFF(“列表差异”的缩写)仍然值得一提。它基于列表的结构(组成列表的 cons 单元格)而不是列表的元素,因此被“减去”的列表必须是 same cons 单元格作为一些尾部的名单。它更具体一点,但它肯定会计算列表差异。

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

【讨论】:

  • 您可能想要引用符号 a、b、c、d、e、f。还要说清楚:缺点单元格必须相同。相同的意思是“相同”。
  • @RainerJoswig 是的,那些应该被引用。我从'(a b c d e f) 开始,然后在SO 的语法突出显示不喜欢“不匹配的单引号”时进行编辑。至于 cons 单元格,答案中提到:“基于列表的结构(即组成列表的 cons 单元格)”,但我可以更清楚地说明。
【解决方案3】:

由于评论中提到了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

【讨论】:

  • 我可能读错了,但这看起来不需要“先到第二个开始[其中第二个是第一个的后缀]”。这个实现不会有takeWhile (flip notElem "def") "abcdefghdef"返回"abc"而不是"abcdefgh",因为它会在"abc"之后停止,因为d"def"的一个元素?
  • @JoshuaTaylor 是的,我认为这是理想的行为。虽然在再次阅读 OP 之后,我同意我可能错了。
猜你喜欢
  • 2017-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-10
  • 2022-03-06
  • 2010-10-25
  • 2011-09-23
  • 1970-01-01
相关资源
最近更新 更多