Clojure,增加一个计数器

时间:2014-07-17 08:46:14

标签: for-loop clojure increment

我的收藏品看起来像这样:

[({:customer_id "111", :product_id "222"})({:customer_id "333", :product_id "444"}{:customer_id "555", :product_id "666"})...]

我想标记"位置"集合中的哈希值。最后,我希望我的哈希看起来像这样:

[({:product_id "222", :number "1"})({:product_id "444", :number "1"}{:product_id "666", :number "2"})...]

我试过这样的话:

(->> (pig/load-clj "resources/test0_file")
(pig/map
     (fn [ord]
       (for [{:keys [product_id]} ord]
         (let [nb (swap! (atom 0) inc)]
           {:product_id product_id :number nb})))) 

但在那种情况下,nb没有递增。谢谢你的帮助

3 个答案:

答案 0 :(得分:5)

map-indexed,assoc和dissoc提供更清晰的解决方案

(def products ['({:customer_id "111", :product_id "222"})
               '({:customer_id "333", :product_id "444"}
                 {:customer_id "555", :product_id "666"})])


    (for [p products] 
      (map-indexed #(dissoc (assoc %2 :number (str (inc %))) :customer_id ) p))
;user=>(({:number 1, :product_id "222"}) ({:number 1, :product_id "444"} {:number 2, :product_id "666"}))

答案 1 :(得分:2)

抵制打太多代码高尔夫球的冲动,这是一个有效的实施方案:

(def products ['({:customer_id "111", :product_id "222"})
               '({:customer_id "333", :product_id "444"}
                 {:customer_id "555", :product_id "666"})])

(defn number-in-list [products]
  (loop [products products counter 1 result []]
     (if (empty? products)
       (seq result)
       (let [[{:keys [product_id]} & ps] products
             updated {:product_id product_id :number (str counter)}]
         (recur ps (inc counter) (conj result updated))))))

(vec (map number-in-list products))

这是另一个:

(vec
  (for [product-list products
        :let [numbers (iterate inc 1)
              pairs (partition 2 (interleave numbers product-list))]]
      (for [[number {:keys [product_id]}] pairs]
        {:product_id product_id :number (str number)})))

正在进行一些解构,但看起来你已经覆盖了它。

我认为输出是你真正想要的,并且由于某种原因需要关注列表的矢量和:number作为字符串。如果不是这种情况,您可以将来电置于seqstrvec

请注意,此实现是纯粹的,不使用任何可变构造。

通常,原子非常罕见,仅用于某种​​(半)全局,可变状态。对于像你这样的问题,使用循环,范围,序列等更为惯用。

为了解决这个问题,这将返回一个无限的自然数序列:

(iterate inc 1)
; think '(1 (inc 1) (inc (inc 1)) ..)

这个位返回一系列数字和产品交错(直到其中一个用完):

(interleave numbers product-list)
; [first_number first_product second_number second_product ..]

然后我们将它分区为对:

(partition 2 ...)
; [[first_number first_product] [second_number second_product] ...]

...最后,对于这些对中的每一对,我们构建了我们想要的记录。

答案 2 :(得分:1)

鉴于

(def data [[{:customer_id "111", :product_id "222"}]
           [{:customer_id "333", :product_id "444"}
            {:customer_id "555", :product_id "666"}]])

然后

(map
 #(map-indexed
   (fn [n m]
     (assoc
       (select-keys m [:product_id])
       :number
       (str (inc n))))
   %)
 data)

(({:number "1", :product_id "222"})
 ({:number "1", :product_id "444"}
  {:number "2", :product_id "666"}))