2016-08-07 11 views
3

リスト内の他のすべての要素に関数(* x 2)を適用し、ループマクロを使用してリスト全体を返したいとします。私がこれまでに作ってみた解決策はこれです:Common Lisp - リスト内の他のすべての要素に関数を適用する

(defun double-every-other (xs) 
    (loop for x in xs by #'cddr collect (* x 2))) 

しかし、これは二重の他のすべての要素と私だけが実行ので、もし、倍増された要素を返します。

(double-every-other '(1 2 3 4)) 

結果は次のようになります。

'(4 8) 

しかし、私は結果になりたい:

'(1 4 3 8) 

(ループ)を使ってこれを行う方法はありますか?あなたは、インスタンスのためにリストを走査しながら増加する整数をテストすることができ

答えて

5

:以下数学と

(defun double-every-other (xs) 
    (loop for x in xs 
    for i from 1 
    if (oddp i) 
    collect x 
    else collect (* x 2))) 
7

別のバージョン:明らか

(defun double-every-other (list) 
    (loop 
    for (a b) on list by #'cddr 
    collect a 
    when b collect (* b 2))) 

(double-every-other '(1 2 3 4)) 
=> (1 4 3 8) 

(double-every-other '(1 2 3 4 5)) 
=> (1 4 3 8 5) 

、あなたは抽象的なNすることはできません他の答えと同じように簡単に(あなたが "マクロ"を考えているなら、今停止する)。ここでは、onキーワードを使用して繰り返します。つまり、各サブリストは順番にアクセスされます。 by #'cddrを使用しているので、他のすべてのサブリストはスキップされます。構造解除構文(a b)は、訪問先リストの第1要素と第2要素をバインドします。

+0

が奇数の要素を持つリストでは動作しません。 – Renzo

+0

@Renzoありがとう、私はそれを逃した – coredump

3
(defun double-every-other (xs) 
    (loop for x in xs 
     for doublep = nil then (not doublep) 
     collect (if doublep (* x 2) x))) 
+0

@Svante:それは遅かった...ありがとう。 –

2

別バージョン、ループなしですべて:

(defun make-cycled (&rest items) 
    (setf (cdr (last items)) items)) 

(mapcar #'funcall 
     (make-cycled #'identity (lambda (x) (* 2 x))) 
     '(10 9 8 7 6 5 4 3)) 

;;=> (10 18 8 14 6 10 4 6) 
+0

甘い、mapcarについて何か新しいことを学んだ。 –

0

あなたは、プリミティブリストの繰り返し "に" loopを使用することができます。これは、リスト全体に「塗りつぶされる」ループ変数のリストを取り、最後は残りのリスト全体の末尾になります。条件付きloopは、奇数の引数がある場合は、nilを乗算しないようにする必要があります。

(defun double-every-other (list) 
    (loop for (single double tail) on list by #'cddr 
    if (null double) 
     collect single 
    else 
     append (list single (* 2 double)))) 

そして、私たちはそれを実行しようとした場合:

* (double-every-other '(1 2 3 4 5)) 

(1 4 3 8 5) 
関連する問題