سؤال

This problem takes many forms. For example, given the input '(1 2 3 4 5 6), we might want to swap the values between even and odd pairs. The output would be '(2 1 4 3 6 5).

In Haskell, this is rather easy:

helper [] = []
helper [x] = [x]
helper (x : y : ys) = y : x : helper ys

I wrote some Clojure code to accomplish the same task, but I feel that there is probably a cleaner way. Any suggestions on how to improve this?

(defn helper [[x y & ys]]
  (cond
   (nil? x) (list)
   (nil? y) (list x)
   :else (lazy-seq (cons y (cons x (helper ys))))))

Ideally the list would be consumed and produced lazily. Thanks.

هل كانت مفيدة؟

المحلول

(for [[a b] (partition 2 '(1 2 3 4 5 6))
      i [b a]]
  i)

OR something resembling the haskell version:

(defn helper
  ([] (list))
  ([x] (list x))
  ([x y & r] (concat [y x] (apply helper r))))

(apply helper '(1 2 3 4 5 6))

نصائح أخرى

Avoiding intermediate object creation (vectors / seqs to be concatenated) and in direct correspondence to the Haskell original while handling nil items in the input (which the approach from the question text doesn't):

(defn helper [[x & [y & zs :as ys] :as xs]]
  (if xs
    (lazy-seq
      (if ys
        (cons y (cons x (helper zs)))
      (list x)))))

Normally I'd use something like tom's answer though, only with mapcat rather than flatten:

(defn helper [xs]
  (mapcat reverse (partition-all 2 xs)))

You need to use partition-all rather than partition to avoid dropping the final element from lists of odd length.

This is one lazy way to do it:

user=> (mapcat reverse (partition 2 '(1 2 3 4 5 6)))
(2 1 4 3 6 5)
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top