簡體   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