问一个简单的问题

100 views
Skip to first unread message

刘杰

unread,
Jan 23, 2014, 10:07:52 PM1/23/14
to cn-cl...@googlegroups.com
Hi ,

我最近开始用clojure写一些代码,有一段程序不知道用clojure怎么写比较好,希望大家指点一下。问题是这样的:

有一个数组 [1 2 3 7 8 9 13 13 14],我想计算相邻两个元素的差,如果大于3,就把之前的元素拿出来作为一个分组,最后返回一个包含所有分组的数组。如刚才那个数组返回的结果希望是 [[1 2 3] [7 8 9] [13 13 14]]。

这个东西用其他语言实现起来都很容易,但是引文用clojure经验不足,不知道clojure怎样实现比较好,比较符合clojure的规范。当让活生生从其他语言翻译过来可能也能有用,但可能不是 the way in clojure。

求指点!

dennis zhuang

unread,
Jan 23, 2014, 10:17:08 PM1/23/14
to cn-cl...@googlegroups.com
一个不那么漂亮的解法:

 (let [prev (atom 0)]
    (partition-by (fn [x]
                    (let [v @prev]
                      (reset! prev x)
                      (if (> (-  x v) 3)
                        0
                        1)))
                  [1 2 3 7 8 9 13 13 14]))


--
中文社区博客:http://blog.clojure.cn/
中文问答网站:http://ask.clojure.cn/
中文邮件列表:https://groups.google.com/d/forum/cn-clojure?hl=zh-CN
---
您收到此邮件是因为您订阅了 Google 网上论坛的“CN-Clojure”论坛。
要退订此论坛并停止接收此论坛的电子邮件,请发送电子邮件到 cn-clojure+...@googlegroups.com
要向此网上论坛发帖,请发送电子邮件至 cn-cl...@googlegroups.com
通过以下网址访问此论坛:http://groups.google.com/group/cn-clojure。
要查看更多选项,请访问 https://groups.google.com/groups/opt_out。



--
庄晓丹
Email:        killm...@gmail.com xzh...@avos.com
Site:           http://fnil.net
Twitter:      @killme2008


dennis zhuang

unread,
Jan 23, 2014, 10:19:24 PM1/23/14
to cn-cl...@googlegroups.com
简化一点:
 (let [prev (atom 0)]
    (partition-by #(let [v @prev]
                              (reset! prev %)
                              (> (-  % v) 3))
                                          [1 2 3 7 8 9 13 13 14]))

刘杰

unread,
Jan 23, 2014, 10:27:43 PM1/23/14
to cn-cl...@googlegroups.com
谢谢 Dennis!

在 2014年1月24日星期五UTC+8上午11时19分24秒,dennis写道:

dennis zhuang

unread,
Jan 23, 2014, 10:55:35 PM1/23/14
to cn-cl...@googlegroups.com
又改了个lazy-seq的版本:

(defn my-partition
  ([coll]
     (my-partition [] coll))
  ([xs coll]
  (lazy-seq
   (when-let [s (seq coll)]
     (let [fst (first s)
           sec (second s)]
       (if (or (nil? sec) (> (- sec fst) 3))
         (cons (conj xs fst) (my-partition [] (next s)))
         (my-partition (conj xs fst) (next s))))))))

(my-partition [1 2 3 7 8 9 13 17 14])

老板原谅我吧,突然想练习练习,哈哈。


Ruiyun Wen

unread,
Jan 23, 2014, 11:07:03 PM1/23/14
to cn-clojure
(defn f [coll]
  (->> (conj coll (last coll))
       (partition 2 1)
       (partition-by #(> (- (second %) (first %)) 3))
       (partition-all 2)
       (map (comp (partial take-nth 2) flatten))))

这个也可以

dennis zhuang

unread,
Jan 23, 2014, 11:08:39 PM1/23/14
to cn-cl...@googlegroups.com
老温这个版本好,完全用高阶函数。

Ruiyun Wen

unread,
Jan 23, 2014, 11:23:17 PM1/23/14
to cn-clojure
呵呵,我也手痒了

刘杰

unread,
Jan 23, 2014, 11:42:58 PM1/23/14
to cn-cl...@googlegroups.com
谢谢你们,受益匪浅!

在 2014年1月24日星期五UTC+8下午12时23分17秒,ruiyun写道:

dennis zhuang

unread,
Jan 24, 2014, 1:25:24 AM1/24/14
to cn-cl...@googlegroups.com
老温,你这个版本有Bug:

(f [1 2 3 7 8 9 13 17 14])

输出:

((1 2 3) (7 8 9 13) (17 14))

13应该是单独一个集合。

xhh

unread,
Jan 24, 2014, 1:29:47 AM1/24/14
to cn-cl...@googlegroups.com
我也写一个, 可能比较初级 :)

(reduce (fn [result i]
          (let [prev (-> result last last)]
            (if (and prev (<= (- i prev) 3))
              (conj (pop result) (conj (peek result) i))
              (conj result [i]))))
        []
        [1 2 3 7 8 9 13 13 14])



许辉辉

张恒

unread,
Jan 24, 2014, 6:19:43 AM1/24/14
to cn-cl...@googlegroups.com
(let [x [1 8 3 6 10 14 11 15]]
  (->> (partition 2 1 x)
       (map #(- (second %) (first %)))
       (map (partial < 3))
       (interleave x )
       (apply vector)
       (#(conj % (last x)))
       (partition-by #(or (number? %) (false? %)))
       (map #(filter number? %))
       (filter seq)))

吃饭去。 

Ruiyun Wen

unread,
Jan 24, 2014, 6:27:47 AM1/24/14
to cn-clojure
是哈,partition-by会把符合条件的都合并了,又用相对索引的方式重新实现了一份,只是这个版本有些太过晦涩,不甚雅观

(defn f [coll]
  (->> (conj coll (last coll))
       (partition 2 1)
       (keep-indexed #(if (> (- (second %2) (first %2)) 3) %1))
       (cons -1)
       (partition 2 1)
       (map #(- (second %) (first %)))
       (reduce #(concat (butlast %1) (split-at %2 (last %1))) [coll])))

此外,如果coll是nil或者空序列的话,结果也算不上合理

julius

unread,
Jan 28, 2014, 2:24:57 AM1/28/14
to cn-cl...@googlegroups.com
(defn partition-nums
  "partition a collection of numbers into groups"
  [coll]
  (loop [left coll
         grouped []]
    (let [cur-num                (first left) ;;the num to be partitioned
          last-group             (last grouped)
          last-num-of-last-group (last last-group)]
      (cond
       (nil? cur-num) grouped
       (or (nil? last-num-of-last-group)
           (< 3 (- cur-num last-num-of-last-group)))
       (recur (next left) (conj grouped [cur-num]))
       :else    (recur
                 (next left)
                 (update-in grouped [(dec (count grouped))] conj cur-num))))))


(deftest test-partition-nums
  (is (= [[1 2] [6]] (partition-nums [1 2 6])))
  (is (= [[1 2 3] [7 8 9] [13 13 14]] (partition-nums [1 2 3 7 8 9 13 13 14]))))

ma ming

unread,
Jan 28, 2014, 7:05:40 AM1/28/14
to cn-cl...@googlegroups.com
(defn partition-when-gap-gt
    "usage:(partition-when-gap-gt 3 [1 2 3 7 8 9 13 13 14])"
    [n coll]
    (when-let [l (seq coll)]
      (loop [l l gps {} gp [] p (first l)]
        (let [c (first l)]
          (if l
        (if (> n (- c p))
          (recur (next l) gps (conj gp c) p)
          (recur (next l) (assoc gps p gp) [c] c))
        (conj (vals gps) gp))))))


--

julius

unread,
Jan 28, 2014, 9:48:55 PM1/28/14
to cn-cl...@googlegroups.com
make a change 


(defn partition-nums1
    "usage:(partition-when-gap-gt 3 [1 2 3 7 8 9 13 13 14])"
    [n coll]
    (when-let [l (seq coll)]
      (loop [l l gps [] gp [] p (first l)]
        (println "" l gps gp p )
        (let [c (first l)]
          (if l
        (if (> n (- c p))
          (recur (next l) gps (conj gp c) p)
          (recur (next l) (conj gps gp) [c] c))
        (conj gps gp))))))

jamesqiugm

unread,
Jan 31, 2014, 11:44:27 PM1/31/14
to cn-cl...@googlegroups.com
(defn f [v]
  (let [v1 (map - (rest v) v)
        n (conj (vec (for [i (range (count v1)) :when (> (nth v1 i) 3)] (inc i))) (count v))
        ij (map vector (cons 0 (butlast n)) n)]
    (for [[i j] ij] (subvec v i j))))


(println (f [1 2 3 7 8 9 13 13 14])) ; ([1 2 3] [7 8 9] [13 13 14])
(println (f [1 2 3 7 8 9 13 17 14])) ; ([1 2 3] [7 8 9] [13] [17 14])
Reply all
Reply to author
Forward
0 new messages