作为一个更大程序的一部分,我正在测试一个函数,该函数将把一个类发生的一系列日子(如"MWF")转换为七个数字的列表:(1 0 1 0 1 1 0 0)。我首先把"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…)以正确的方式来做这件事,"但我不知道如何用(map)来做。所以,我的两个问题是:
1) 有"Clojure方式"这样的东西吗?如果有,2) 如何重写代码以使其更像Clojure?
您可以使用地图并设置
使用地图和集合:
(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)))
这就是我更简洁的做法:
(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)
下面是@TheQuickBrownFox的回答。。。
- 您不需要重新编码
"TH"
和"SU"
:第二个字母将做 - 使用
false
或nil
而不是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}