繁体   English   中英

列表或向量上相同的头部和尾部操作

[英]identical head and tail operations on lists or vectors

我没有LISP和列表处理方面的经验,但是我有一组C ++ STL向量(或字符串),我需要在这些向量上执行以下操作:

IdenticalHead(v1,v2):返回v1和v2都以此序列开头的最大序列。

IdenticalTail(v1,v2):返回v1和v2都以其结尾的最大序列。

IdenticalTailHead(v1,v2):返回以v1结束并以v2开头的最大序列。

例如:

如果v1 =(a,b,c,e,f),v2 =(a,b,d,e,f),则:

IdenticalHead (v1, v2) = (a,b)
IdenticalTail (v1, v2) = (e,f)

如果v1 =(a,b,c),v2 =(b,c,g),则:

IdenticalTailHead (v1, v2) = (b,c)

我的问题是这些标准操作是使用LISP还是其他语言进行的? 他们有CDR和CAR等标准名称吗?

IdenticalHead和IdenticalTail基本上由Common Lisp函数MISMATCH提供

CL-USER 81 > (mismatch '(a b c e f) '(a b d e f))
2

CL-USER 82 > (mismatch '(a b c e f) '(a b d e f) :from-end t)
3

CL-USER 83 > (defun identical-head (s1 s2)
               (let ((m (mismatch s1 s2)))
                 (if (numberp m)
                     (subseq s1 0 m)
                   s1)))
IDENTICAL-HEAD

CL-USER 84 > (identical-head '(a b c e f) '(a b d e f))
(A B)

CL-USER 85 > (defun identical-tail (s1 s2)
               (let ((m (mismatch s1 s2)))
                 (if (numberp m)
                   (subseq s1 (1+ m))
                   s1)))
IDENTICAL-TAIL

CL-USER 86 > (identical-tail '(a b c e f) '(a b d e f))
(E F)

第三个功能更复杂:

CL-USER 87 > (defun identical-tail-head (s1 s2 &aux (l1 (length s1)))
               (loop for i from 0 below l1
                     for m = (mismatch s2 s1 :start2 i)
                     when (and m (= (+ i m) l1))
                     do (return (subseq s1 i))))

CL-USER 88 > (identical-tail-head '(a e d b c d) '(b c d a f))
(B C D)

不,没有这些的标准运算符。 但是identical-head并不难写:

(defun identical-head (l1 l2)
  (and l1 l2 (equal (car l1) (car l2))
       (cons (car l1) (identical-head (cdr l1) (cdr l2)))))

除了反转输入列表,调用identical-head ,然后反转结果之外,我不知道一种编写identical-tail的简便方法,因为列表仅允许向前遍历,而不允许向后遍历。

(defun identical-tail (l1 l2)
  (reverse (identical-head (reverse l1) (reverse l2))))

这是我写identical-tail-head

(defun identical-tail-head (l1 l2)
  (labels ((starts-with-p (list prefix)
             (cond ((null prefix) t)
                   ((null list) nil)
                   ((equal (car list) (car prefix))
                    (starts-with-p (cdr list) (cdr prefix))))))
    (cond ((null l1) nil)
          ((starts-with-p l2 l1) l1)
          (t (identical-tail-head (cdr l1) l2)))))

这不是一种非常有效的方法,因为它是O(n²),但是(再次)鉴于列表仅是向前遍历的,所以我没有想出更好的方法。

因为您提到“其他语言”,所以Haskell是一种Lispy语言,它确实对您要问的内容有惯用的方法。

longestPrefix xs ys = map fst (takeWhile (\(x,y) -> x == y) (zip xs ys))

zip将其两个参数列表的元素配对,并且takeWhile是自描述的。

对于第二个变体,您只需要对参数和结果使用reverse 第三点涉及更多:

longestPrefixEnding xs ys =   -- '(a e d b c d) '(b c d a f)
  head [t  |  t <- tails xs, let p=longestPrefix t ys, p==t]

tails xs等效于iterate tail xs tails xs ,即列表[xs, tail xs, tail (tail xs), ...] tailcdr的同义词,而headcar同义词:

Prelude Data.List> longestPrefix "abcef" "abdef"
"ab"
Prelude Data.List> longestPrefixEnding "aedbc" "bcdaf"
"bc"
Prelude Data.List> longestPrefixEnding "aebcabcd" "bcdaf"
"bcd"
Prelude Data.List> longestPrefixEnding "aebcabcdx" "bcdaf"
""

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM