2013-07-22 23 views
6

に長さの異なる2つのリストをアップジップ:は、私は二つのリストを持っているelispの

(setq x (list "a" "b" "c")) 
(setq y (list "1" "2" "3" "4")) 

にはどうすればコンスセルリサイクル短いリストを(("a" . "1") ("b" . "2") ("c" . "3") ("a" . "4"))のリストを作成することができますか?

+0

実際には、循環リストがこの場合に役立つと思いました。それは変わらない... – RNA

答えて

6

が私の感想ですそのうちのどれが大きいかをチェックしますが、それは簡潔さを損なうでしょう:)。

+0

偉大な解決策 - 私が探しているもの。ありがとう! – RNA

+0

元のリストを変更したくない場合は、 'x'と' y'の短い方に 'copy-sequence'を使い、その新しいリストに' setcdr'を使います。 – Drew

1

あり、それを行うための簡単な方法は確かであるが、ここでは無限リストに入力シーケンスをオンバージョンだし、それらをzip圧縮:

(require 'cl-lib) 
(cl-mapcar #'list (setcdr (last x) x) y) 

I:ここで

(defun* cycle-iterator (xs &optional (idx 0) (len (length xs))) 
    "Create an iterator that will cycle over the elements in XS. 
Return a cons, where the car is the current value and the cdr is 
a function to continue the iteration." 
    (cons (nth (mod idx len) xs) 
     (eval `(lambda() (cycle-iterator ',xs ,(1+ idx) ,len))))) 

(defun cycle-take (xs n) 
    "Take N elements from XS, cycling the elements if N exceeds the length of XS." 
    (loop 
    when (plusp n) 
    ;; Creating the iterator returns the first value. Subsequent calls can then 
    ;; be processed in a loop. 
    with (value . iterator) = (cycle-iterator xs) 
    with acc = (list value) 
    repeat (1- n) do (destructuring-bind (val . next) (funcall iterator) 
         (setq iterator next) 
         (setq acc (cons val acc))) 
    finally (return (nreverse acc)))) 

(defun cycling-zip (xs ys) 
    "Zip XS and YS together, cycling elements to ensure the result 
    is as long as the longest input list." 
    (loop 
    with limit = (max (length xs) (length ys)) 
    for x in (cycle-take xs limit) 
    for y in (cycle-take ys limit) 
    collect (cons x y))) 


;; Usage: 
(cycling-zip '("a" "b" "c") '("1" "2" "3" "4")) 
; => (("a" . "1") ("b" . "2") ("c" . "3") ("a" . "4")) 
1

この回答は、dashリスト操作ライブラリが必要です。あなたの問題を攻撃する前に、には、最長のリストの長さを見つけるのが良いです。私が思いついた最初の方法は次のとおりです。

(require 'dash) 
(require 'dash-functional) 
(length (-max-by (-on '> 'length) (list x y))) ; 4 

-onは、コンパレータを受け入れるパッケージdash-functionalからスマート機能、比較する上での鍵であり、このキーに比較する関数を返します。したがって、(-max-by (-on '> 'length) xs)は、xsの要素を見つけます。その要素のです。しかし、この表現は自分自身にとってはあまりにもスマートです。dash-functionalは、字句的なスコープのためにEmacs 24でしか動作しません。 Python solutionに触発され、のは、それを書き換えてみましょう:

(-max (-map 'length (list x y))) ; 4 

(-take n (-cycle xs))を行い、無限cycledリストから最初のnの要素を取ること。したがって、より小さなリストから要素が繰り返される連想リストを作成するには、書き込み:

(let ((len (-max (-map 'length (list x y))))) 
    (flet ((cycle (xs) (-take len (-cycle xs)))) 
    (-zip (cycle x) (cycle y)))) ; (("a" . "1") ("b" . "2") ("c" . "3") ("a" . "4")) 
0

私はlispのための自然に思えた再帰的なアプローチを行ってきました。

(defun zip (xs ys) 
    (cond 
    ((or (null xs) (null ys))()) 
    (t (cons (cons (car xs) (car ys)) (zip (cdr xs) (cdr ys)))))) 
関連する問題