简体   繁体   English

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

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

I am not experienced in LISP and list processing, but I have a set of C++ STL vectors (or strings) on which I need to perform the following operations: 我没有LISP和列表处理方面的经验,但是我有一组C ++ STL向量(或字符串),我需要在这些向量上执行以下操作:

IdenticalHead (v1, v2): Return the biggest sequence that both v1 and v2 start with it. IdenticalHead(v1,v2):返回v1和v2都以此序列开头的最大序列。

IdenticalTail (v1, v2): Return the biggest sequence that both v1 and v2 end with it. IdenticalTail(v1,v2):返回v1和v2都以其结尾的最大序列。

IdenticalTailHead (v1, v2): Return the biggest sequence that v1 ends with it and v2 starts with it. IdenticalTailHead(v1,v2):返回以v1结束并以v2开头的最大序列。

For example: 例如:

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

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

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

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

My question is that are these standard operations in LISP or any other language? 我的问题是这些标准操作是使用LISP还是其他语言进行的? Do they have standard names like CDR and CAR? 他们有CDR和CAR等标准名称吗?

IdenticalHead and IdenticalTail are basically provided by the Common Lisp function MISMATCH . 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)

The third function is more complicated: 第三个功能更复杂:

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)

No, there are no standard operators for these. 不,没有这些的标准运算符。 But identical-head is not hard to write: 但是identical-head并不难写:

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

I don't know of an easier way to write identical-tail except reversing the input lists, calling identical-head , and then reversing the result, since lists only allow forward traversal, not backward. 除了反转输入列表,调用identical-head ,然后反转结果之外,我不知道一种编写identical-tail的简便方法,因为列表仅允许向前遍历,而不允许向后遍历。

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

Here's how I'd write identical-tail-head : 这是我写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)))))

It's not a very efficient way to do it, since it's O(n²), but (again) given that lists are forward-traversal-only, I haven't come up with a better way. 这不是一种非常有效的方法,因为它是O(n²),但是(再次)鉴于列表仅是向前遍历的,所以我没有想出更好的方法。

Since you mention "other language", Haskell is a kind-of Lispy language, and it does have idiomatic approach to what you're asking about. 因为您提到“其他语言”,所以Haskell是一种Lispy语言,它确实对您要问的内容有惯用的方法。

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

zip pairs up the elements of its two argument lists, and takeWhile is self-descriptive. zip将其两个参数列表的元素配对,并且takeWhile是自描述的。

For the second variant you'd just use reverse on arguments and on the result. 对于第二个变体,您只需要对参数和结果使用reverse The third is a bit more involved: 第三点涉及更多:

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 is equivalent to iterate tail xs ie the list [xs, tail xs, tail (tail xs), ...] ; tails xs等效于iterate tail xs tails xs ,即列表[xs, tail xs, tail (tail xs), ...] tail is a synonym of cdr , and head - synonym of car : 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