[英]Capitalize Every Other Letter in a String — take / drop versus head / tail for Lists
[英]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), ...]
; tail
是cdr
的同义词,而head
是car
同义词:
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.