使用clojure格式化

时间:2015-12-08 19:42:07

标签: list clojure formatting set comparison

上下文

我有一个列表和一组包含两种不同格式的类似数据。

("XXX_1_10/22/2015" "YYY_1.5_11/22/2015" "XX_2.5_10/23/2015" "YY_5_11/26/2015")

#{"XXX 1.000 OCT15" "XX 2.500 OCT2015" "ZZZ 3.500 JAN2016"}

我需要获得这两个数据结构之间通用的列表 Clojure的。

应该是:

("XXX 1.000 OCT15" "XX 2.500 OCT2015")

问题

有人可以帮我解决这个问题。

1 个答案:

答案 0 :(得分:0)

您必须先将所有值标准化。使用regexp来做。

(def months ["JAN" "FEB" "MAR" "APR" 
             "MAY" "JUN" "JUL" "AUG" 
             "SEP" "OCT" "NOV" "DEC"])

(defn normalize-underscored [value]
  (let [[_ text val month year]
        (re-matches #"(.+?)_([\d.]+)_(\d+)/\d+/(\d{4})" value)]
    [text
     (Float/parseFloat val)
     (months (dec (Long/parseLong month)))
     year]))

(defn normalize-spaced [value]
  (let [[_ text val month year]
        (re-matches #"(.+?)\s([\d.]+)\s(\w{3})(\d{2,4})" value)]
    [text (Float/parseFloat val) month
     (if (== 2 (count year)) (str "20" year) year)]))

它是如何规范化的:

user> (normalize-underscored "XX_2.5_10/23/2015")
["XX" 2.5 "OCT" "2015"]
user> (normalize-spaced "XXX 1.000 OCT15")
["XXX" 1.0 "OCT" "2015"]
user> (normalize-spaced "ZZZ 3.500 JAN2016")
["ZZZ" 3.5 "JAN" "2016"]

然后只比较规范化版本:

(def underscored '("XXX_1_10/22/2015" "YYY_1.5_11/22/2015"
                   "XX_2.5_10/23/2015" "YY_5_11/26/2015"))

(def spaced #{"XXX 1.000 OCT15" "XX 2.500 OCT2015" 
              "ZZZ 3.500 JAN2016"})

(for [uv (map normalize-underscored underscored)
      s spaced
      :when (= uv (normalize-spaced s))]
  s)

输出:

("XXX 1.000 OCT15" "XX 2.500 OCT2015")

或者更好地将结果重新格式化为更一致的形式,如下所示:

(map (partial apply format "%s %.3f %s%s")
     (keep (set (map normalize-spaced spaced))
           (map normalize-underscored underscored)))

输出:

("XXX 1.000 OCT2015" "XX 2.500 OCT2015")