2013-03-05 67 views
9

什麼會是一個更基於seq整數而不是一個整數分割seq的慣用方法?由整數seq分區

這裏是我的實現:

(defn partition-by-seq 
    "Return a lazy sequence of lists with a variable number of items each 
    determined by the n in ncoll. Extra values in coll are dropped." 
    [ncoll coll] 
    (let [partition-coll (mapcat #(repeat % %) ncoll)] 
    (->> coll 
     (map vector partition-coll) 
     (partition-by first) 
     (map (partial map last))))) 

然後(partition-by-seq [2 3 6] (range))產生((0 1) (2 3 4) (5 6 7 8 9 10))

回答

3

上ANKUR的回答的變種,與未成年人除了懶惰和when-let而不是爲empty?的明確的測試。

(defn partition-by-seq [parts coll] 
    (lazy-seq 
     (when-let [s (seq parts)] 
     (cons 
      (take (first s) coll) 
      (partition-by-seq (rest s) (nthrest coll (first s))))))) 
+0

我喜歡在這裏使用'when-let',因爲(cons x nil)只是(x),並且發現比「if」版本更清潔。爲什麼使用'nthrest'而不是'drop'?看起來內部部分可能是'(when-let [n(first parts)](cons(take n coll)(partition-by-seq(rest parts)(drop n coll))))' – ToBeReplaced 2013-03-05 20:02:41

+0

@ToBeReplaced' nthrest'只是急速下降的'drop',我認爲在這種情況下是合適的。再次想到,我不確定它是否重要。事實上,'第一個'可以在'when-let'中移動。 – 2013-03-05 20:22:32

2
(first (reduce (fn [[r l] n] 
       [(conj r (take n l)) (drop n l)]) 
       [[] (range)] 
       [2 3 6])) 

=> [(0 1) (2 3 4) (5 6 7 8 9 10)] 
+0

'reduce'更是不可以偷懶 – Ankur 2013-03-05 16:47:36

+0

人......不會減少一切... – ToBeReplaced 2013-03-05 20:06:56

4

你的實現看起來不錯,但也可能是一個更簡單的解決方案,它使用簡單的遞歸包裹在lazy-seq(和原來是更有效率)比使用地圖和現有的分區,通過在你的情況。

(defn partition-by-seq [ncoll coll] 
    (if (empty? ncoll) 
    '() 
    (let [n (first ncoll)] 
     (cons (take n coll) 
      (lazy-seq (partition-by-seq (rest ncoll) (drop n coll))))))) 
+1

這可以作出甚至懶惰,採取'懶seq'外'cons',這樣,即使第一個'(以並不急於評估。 – 2013-03-05 19:13:17