什么是clojure做事的方式

时间:2014-09-23 01:29:28

标签: clojure

作为一个更大的计划的一部分,我正在测试一个函数,该函数将一个类发生的天数(例如" MWF")转换成七个数字的列表:( 1 0 1 0 1 0 0)。 我首先翻译了#34; TH" (星期四)到" R"和" SU" (星期日)到" N"让事情变得更容易。

我想出了以下代码:

(defn days-number-maker
  "Recursively compare first item in days of week with
first item in string of days. If matching, add a 1,
else add a zero to the result"
  [all-days day-string result]
  (if (empty? all-days) (reverse result)
    (if (= (first all-days) (first day-string))
      (recur (rest all-days)(rest day-string) (conj result 1))
      (recur (rest all-days) day-string (conj result 0)))))

(defn days-to-numbers
  "Change string like MTTH to (1 1 0 1 0 0 0)"
  [day-string]
  (let [days (clojure.string/replace
               (clojure.string/replace day-string #"TH" "R") #"SU" "N")]
    (days-number-maker "MTWRFSN" days (list))))

好消息:代码有效。坏消息:在道德纯洁的意义上,我确信我做错了。我内心的某些东西说,"你可能刚刚使用(map ...)以正确的方式执行此操作,"但我无法看到如何使用(地图)。所以,我的两个问题是:

1)是否存在" Clojure方式,"如果是这样, 2)如何将代码重写为更多Clojure-ish?

3 个答案:

答案 0 :(得分:3)

您可以使用地图和集

使用地图和集合:

(defn days-number-maker
  [all-days day-string]
  (let [day-set (set day-string)]
    (map (fn [day]
           (if (day-set day)
             1
             0))
         all-days)))

(defn days-to-numbers
  "Change string like MTTH to (1 1 0 1 0 0 0)"
  [day-string]
  (let [days (clojure.string/replace
               (clojure.string/replace day-string #"TH" "R") #"SU" "N")]
    (days-number-maker "MTWRFSN" days)))

答案 1 :(得分:1)

这就是我如何更简洁地做到这一点:

(defn days-to-numbers
  "Change string like MTTH to (1 1 0 1 0 0 0)"
  [week-string]
  (let [char-set (set (clojure.string/replace
                        (clojure.string/replace week-string "TH" "R") "SU" "N"))]
    (map #(if (char-set %) 1 0)
         "MTWRFSN")))

试验:

=> (days-to-numbers "")
(0 0 0 0 0 0 0)
=> (days-to-numbers "MTWTHFSSU")
(1 1 1 1 1 1 1)
=> (days-to-numbers "MTHSU")
(1 0 0 1 0 0 1)
=> (days-to-numbers "FM")
(1 0 0 0 1 0 0)

答案 2 :(得分:0)

继续@TheQuickBrownFox's answer ...

  • 您不需要重新编码"TH""SU":第二个字母将会 做。
  • 使用falsenil代替0,以便您可以直接应用逻辑测试。
  • 将结果作为向量返回,因为您很可能想要这样做 索引。

给予......

(defn days-to-numbers [ds]
  (let [dns (->> ds
             (partition-all 2 1)
             (remove #{[\S \U] [\T \H]})
             (map first)
             set)]
    (mapv dns "MTWHFSU")))

例如,

(days-to-numbers "MTTH")
;[\M \T nil \H nil nil nil]

虽然函数名称错误,但元素是逻辑值,而不是数字。


我更愿意返回日期数字的

(def day-index (into {} (map-indexed (fn [x y] [y x]) "MTWHFSU")))
;{\M 0, \T 1, \W 2, \H 3, \F 4, \S 5, \U 6}

(defn day-numbers [ds]
  (->> ds
       (partition-all 2 1)
       (remove #{[\S \U] [\T \H]})
       (map (comp day-index first))
       set)) 

例如,

(day-numbers "MTTH")
;#{0 1 3}