2014-03-13 77 views
0

我想遍歷一個映射來計算個別事件的特定事件,雖然我在使用過濾器時遇到了一些麻煩,如下所示。我想要做的是過濾並計算每個「ORDER_CATEGORY」的特定實例,這些實例出現在多個級別中 - 1,2等等。我能夠迭代儘管月份和打印,但過濾器和計數我已經爲ORDER_CATEGORY的似乎沒有爲我工作。Clojure - 使用過濾器

[ 「01」[:

GROUPED_BY_MONTH(group-by :MONTH CON) 

ALL (for [flop GROUPED_BY_MONTH] { 
    :MONTH (:MONTH (first (second flop))) 
    :ORDER1 (count (filter #(= "1" (:ORDER_CATEGORY %)) flop)) 
    :ORDER2 (count (filter #(= "2" (:ORDER_CATEGORY %)) flop)) 
}) 

我與我所成功地管理爲一體拼接列表和如下分組XML文件{:MONTH 「01」,:ORDER_CATEGORY 「1」} { :MONTH「01」,:ORDER_CATEGORY「1」} {:MONTH「01」,:ORDER_CATEGORY「2」}]] [「02」[::MONTH「02」,:ORDER_CATEGORY「1」} {:MONTH「 02" ,:ORDER_CATEGORY 「2」} {:月 「02」,:ORDER_CATEGORY 「2」}]]

因此,我期望有:

月ORDER1 ORDER2

01 -------- 2 -------------- 1

02 -------- 1 ------ -------- 2

這可能是一個相對簡單的修復程序,我忽略了所以感謝提前的幫助!

+1

你可以嘗試構建一個獨立的複製器 - 也就是說,其他人可以運行的東西,而不需要定義不包括在這裏?另見http://www.sscce.org/。 –

回答

1

您的循環是不行的,因爲你已經綁定映射條目像這樣flop

["01" [{:MONTH "01", :ORDER_CATEGORY "1"} ...]]

而且你的過濾器表達式採取作爲輸入:

(filter #(= "1" (:ORDER_CATEGORY %)) flop)

這是行不通的,因爲:ORDER_CATEGORY既不會返回某物。對於"01",也對於序列[{:MONTH ...} ...]

既然你已經綁定到flop是MapEntry,您可以使用val來解決這個問題:

(filter #(= "1" (:ORDER_CATEGORY %)) (val flop))

E.g。:

(for [flop GROUPED_BY_MONTH] 
    {:MONTH (:MONTH (first (second flop))) 
    :ORDER1 (count (filter #(= "1" (:ORDER_CATEGORY %)) (val flop))) 
    :ORDER2 (count (filter #(= "2" (:ORDER_CATEGORY %)) (val flop)))}) 
=> ({:MONTH "01", :ORDER1 2, :ORDER2 1} {:MONTH "02", :ORDER1 1, :ORDER2 0}) 

你也可以使用destructoring,使你的代碼更加清晰:

(for [[month maps] GROUPED_BY_MONTH] 
    {:MONTH month 
    :ORDER1 (count (filter #(= "1" (:ORDER_CATEGORY %)) maps)) 
    :ORDER2 (count (filter #(= "2" (:ORDER_CATEGORY %)) maps))}) 
=> ({:MONTH "01", :ORDER1 2, :ORDER2 1} {:MONTH "02", :ORDER1 1, :ORDER2 0}) 

注意,在一般情況下,這種解決方案更有利:

(reduce (fn [acc {:keys [MONTH ORDER_CATEGORY]}] 
      (update-in acc [MONTH ORDER_CATEGORY] 
        (fnil inc 0))) 
     {} CON) 
=> {"02" {"1" 1}, "01" {"2" 1, "1" 2}} 

它返回一個地圖month->order-category->count,它獨立於輸入集中的訂單類別和月份的種類和類型。

E.g。

(reduce (fn [acc {:keys [MONTH ORDER_CATEGORY]}] 
      (update-in acc [MONTH ORDER_CATEGORY] 
        (fnil inc 0))) 
     {} (conj CON 
       {:MONTH "01" :ORDER_CATEGORY "foo"} 
       {:MONTH "02" :ORDER_CATEGORY "foo"} 
       {:MONTH "02" :ORDER_CATEGORY "bar"} 
       {:MONTH "02" :ORDER_CATEGORY "1"})) 
=> {"02" {"bar" 1, "foo" 1, "1" 2}, "01" {"foo" 1, "2" 1, "1" 2}} 

但是你應該知道,在一個ORDER_CATEGORY計數0的情況下,沒有價值的結果有關。

2

我會首先將數據轉換爲:

user=> (pprint x) 
[{:MONTH "01", :ORDER_CATEGORY "1"} 
{:MONTH "01", :ORDER_CATEGORY "1"} 
{:MONTH "01", :ORDER_CATEGORY "2"} 
{:MONTH "02", :ORDER_CATEGORY "1"}] 

和使用功能:

user=> (defn inc1 [x] (if x (inc x) 1)) 
user=> (reduce (fn [acc {:keys [MONTH ORDER_CATEGORY]}] 
        (update-in acc [[MONTH ORDER_CATEGORY]] inc1)) {} x) 
{["02" "1"] 1, ["01" "2"] 1, ["01" "1"] 2} 

主要是[月份類別],價值是訂單數量。

+1

你可以這樣「首先轉換數據」:'(apply concat(vals(into {} GROUPED_BY_MONTH)))'。 – Thumbnail

+0

感謝您的回覆。我明白你來自哪裏,但是我正在使用的編譯器使用鍵向表中添加標題,因此我爲什麼要循環訪問它。奇怪的是,當我使用循環與過濾器,因爲我已經在上面發佈了它的工作月01,但隨後數據混亂了02和03月...我認爲它的東西相對簡單,我失蹤在代碼中,如果它在02和03月再次循環時錯過了計數/過濾器? – Paul

+0

你可以添加** clojure **代碼和運行代碼的結果嗎? – edbond