給定2個列表,你怎樣才能生成第三個列表的輸出,它的元素是L1和L2的交錯集合?如果它們長度不均勻,則應該插入零孔。在第二個音符上,我該如何反轉一個列表?我對LISP超級新手,只是修改現有的代碼...我真的很喜歡有一個很好的解釋,而不僅僅是代碼。如何在LISP中插入2個列表的元素?
回答
首先,我猜你使用Common Lisp,因爲它是Lisp課程中最常用的一個。所以,我的例子將在CL。如果你使用Scheme,你將得到幾乎相同的代碼。如果現代Clojure,它將需要一些改變,通過一個想法將是相同的。
交錯
交錯2只列出了必須要經過他們兩個,收集輪流元素。你可以使用循環語句或遞歸來做到這一點。我將使用遞歸,因爲它具有更多的功能風格,並且可以在任何lisp中使用,而不僅僅是CL。還要注意,有一個名爲tail recursion的功能,它可以讓您編寫將被編譯爲循環的遞歸函數。
因此,對於我們的函數骨架結構將是:
(defun interleave (l1 l2)
??????
(interleave ?????))
收集在遞歸函數的項目,你將需要從每個調用返回他們,然後負面因素在一起(你必須有一個參數一個尾遞歸,這將積累價值)。所以,該功能的結束將是(cons current-value (interleave ????))
。 此外,您必須備用列表才能使用彼此的元素。您可能有其他參數,但您也可以在遞歸調用中交換它們。因此,代碼變爲:
(defun interleave (l1 l2)
?????
(cons current-value (interleave l2 l1)))
任何遞歸都必須在某處停止。在這種情況下,當兩個列表都爲空(零)時,它必須停止。 這是一個條件(讓它給號碼1),並且還有一些條件:
2.如果要從其中取出的列表是空的,而另一個不是,我們必須取而代之。
3.如果兩個列表都不爲空,則將第一個元素作爲當前值並繼續處理它的尾部。
只有一個更多的條件,2列表可以在:列表採取是不是空的,第二個是。但實際上我們並不關心這個,並且可以與規則編號前進3 因此,該代碼(這是最後一個):
(defun interleave (l1 l2)
(cond ((and (eql l1 nil) (eql l2 nil)) nil) ;; rule #1
((eql l1 nil) (cons nil (interleave l2 l1))) ;; rule #2, current value is nil
(true (cons (first l1) (interleave l2 (rest l1)))))) ;; rule #3 in all other cases
反向
我我們將展示這個函數的兩個實現:一個使用cond
,另一個使用內置的reduce
函數,這在實踐中非常有用。
爲cond
版本第一種方法是要經過所有的列表與遞歸調用,然後回去,收集要素:
(defun reverse-1-1 (li)
(if (eql li nil)
nil
(append (reverse-1-1 (rest li))
(list (first li)))))
但是,這是非常低效的,因爲append爲O(n),你必須通過n個元素,所以最終的複雜度是O(n^2)。
要減少它,你可以使用一個多參數的函數(並使其尾遞歸,如果編譯器可以讓你):
(defun reverse-1-2 (li)
(reverse-aux li nil))
(defun reverse-aux (li accumulator)
(if (eql li nil)
accumulator
(reverse-aux (rest li) (cons (first li) accumulator))))
這就是你用一個參數來收集你的元素,但通過該列表,然後只是返回這個累加器。
還有一個更有趣的選項。 Lisp具有非常強大的功能reduce
(在其他功能語言中,它有時被稱爲fold
,foldr
,foldl
或類似的東西)。您可能會發現說明它here,我會只顯示一個例子:
(defun reverse-2 (li)
(reduce #'cons li :from-end t :initial-value nil))
:from-end
告訴函數要經過單從末尾,:初始值告訴作爲首先減少使用論點nil
。
注意:在某些實現中,減少選項:from-end true
可能首先自行反向列表,因此如果您需要從頭創建或使用最有效的版本,請改爲使用reverse-1-2
。
Common Lisp中:
(defun merge-lists (lst1 lst2)
(let ((m (max (length lst1) (length lst2))))
(flatten (mapcar (lambda (a b) (list a b))
(append-nulls lst1 m)
(append-nulls lst2 m)))))
實例:
(merge-lists '(1 2 3 4) '(5 6 7 8)) ;; => (1 5 2 6 3 7 4 8)
(merge-lists '(1 2 3 4) '(5 6 7)) ;; => (1 5 2 6 3 7 4 NULL)
(merge-lists '(1 2) '(5 6 7 8)) ;; => (1 5 2 6 NULL 7 NULL 8)
的輔助函數flatten
和append-nulls
:
(defun flatten (tree)
(let ((result '()))
(labels ((scan (item)
(if (listp item)
(map nil #'scan item)
(push item result))))
(scan tree))
(nreverse result)))
(defun append-nulls (lst n)
(if (< (length lst) n)
(dotimes (i (- n (length lst)))
(setq lst (append lst (list 'null)))))
lst)
:
(defun interleave (l1 l2)
(cond ((and (eql l1 nil) (eql l2 nil)) nil) ;; rule #1
((eql l1 nil) (cons nil (interleave l2 l1))) ;; rule #2, current value is nil
(true (cons (first l1) (interleave l2 (rest l1)))))) ;; rule #3 in all other cases
如果其中一個列表比另一個長,你會得到類似於(1 2 3 4 nil 5)的東西。 替換: ((EQL L1無)(利弊零(交織L2 L1)))
用: ((空L1)L2)
:P
的更慣用的一個例子在Common Lisp中的解決方案:
(defun interleave (a b)
(flet ((nil-pad (list on-list)
(append list (make-list (max 0 (- (length on-list) (length list)))))))
(loop for x in (nil-pad a b)
for y in (nil-pad b a)
append (list x y))))
- 1. 在common-lisp中,如何將元素插入到列表中?
- 2. Lisp將一個元素插入到子列表中
- 3. 如何加入2個列表,其中一個列表包含2個元素?
- 4. 如何在lisp中將多個列表的元素合併爲一個列表
- 5. 在Lisp列表中交換元素
- 6. 如何將列表中的元素插入到列表中?
- 7. lisp交換列表元素
- 8. Lisp - Lisp的元素出現在其他列表中
- 9. Lisp,如何從列表中刪除元素列表?
- 10. OCaml在列表中插入元素
- 11. 在AsyncTask列表中插入元素
- 12. 在鏈接列表中插入元素
- 13. LISP - 用列表中的第一個元素劃分列表
- 14. 如何在有序列表中插入DOM元素(在Dojo中)?
- 15. 在Lisp中組合2個列表
- 16. 如何在LISP中創建列表並接受用戶列表中的元素?
- 17. 如何在單位矩陣的對角元素中插入列表的元素?
- 18. 如何在最後的列表中插入元素?
- 19. 從lisp列表中獲取元素
- 20. Lisp從列表中獲取元素
- 21. 在列表中插入元素,索引包含在列表中
- 22. 將一個列表的元素插入另一個列表
- 23. Common Lisp:讀取每個輸入字符作爲列表元素
- 24. 如何在任意位置插入元素到列表中?
- 25. 在列表中的特定位置插入一個元素
- 26. 將列表中的每個元素與另一個列表中的每個元素相乘lisp
- 27. 將元素插入到R列表中
- 28. LISP中列表中前n個元素的反向
- 29. Android,Java:返回3個元素列表中的2個元素
- 30. LISP FUNCTION - 返回列表中第一個元素大的列表數的個數
我添加了「作業」標記,以確保人們給出比代碼更多的解釋。 – Gabe 2010-10-19 22:57:28
看到這個問題的一些提示(來自Haskell的庫):http://stackoverflow.com/questions/3938438/merging-two-lists-in-haskell – 2010-10-20 06:23:03