【问题标题】:Clojure: Iterate loop in both conditions of "IF"Clojure:在“IF”的两个条件下迭代循环
【发布时间】:2019-03-25 14:07:47
【问题描述】:

我是 clojure 的新手,一直在尝试解决一个问题,其中包含地图向量的问题

({:disease Asthma, :st-dt 2018-2-1, :en-dt 2018-4-1, :dose 0.25} 
{:disease Asthma, :st-dt 2018-3-1, :en-dt 2018-6-5, :dose 0.65} 
{:disease BP, :st-dt 2018-5-1, :en-dt 2018-9-1, :dose 0.75})

是给定的,我必须得到一个不重叠的数据,有点像

({:disease Asthma, :st-dt 2018-2-1, :en-dt 2018-2-28, :dose 0.25} 
{:disease Asthma, :st-dt 2018-3-1, :en-dt 2018-4-1, :dose 0.25} 
{:disease Asthma, :st-dt 2018-3-1, :en-dt 2018-4-1, :dose 0.65} 
{:disease Asthma, :st-dt 2018-4-2, :en-dt 2018-4-30, :dose 0.65} 
{:disease Asthma, :st-dt 2018-5-1, :en-dt 2018-6-5, :dose 0.65} 
{:disease BP, :st-dt 2018-5-1, :en-dt 2018-6-5, :dose 0.75}
{:disease BP, :st-dt 2018-6-6, :en-dt 2018-9-1, :dose 0.75})

我尝试过使用循环和递归,但我认为在 if 的两种情况下都不可能递归。

(defn ab [x] (let [temp x olap (f/overlap (f/interval ((first temp ):st-dt) ((first temp ):en-dt)) 
                                          (f/interval ((second temp):st-dt) ((second temp):en-dt) ))]
               (if olap 
                 (into [] (concat [{:med-type ((first temp ):med-type) :st-dt ((first temp ):st-dt)
                                    :en-dt (f/minus ((second temp) :st-dt) (f/days 1)) :dose ((first temp):dose )}
                                   {:med-type ((first temp ):med-type) :st-dt ((second temp ):st-dt)
                                    :en-dt ((first temp) :en-dt) :dose ((first temp):dose )}
                                   {:med-type ((second temp ):med-type) :st-dt ((second temp ):st-dt)
                                    :en-dt ((first temp) :en-dt) :dose ((second temp):dose )}
                                   {:med-type ((second temp ):med-type) :st-dt (f/plus ((first temp ):en-dt) (f/days 1))
                                    :en-dt ((second temp) :en-dt) :dose ((second temp):dose )}] 
                                  (into [] (rest (rest x))))))))

【问题讨论】:

    标签: recursion vector clojure tail-recursion


    【解决方案1】:

    仅回答问题(而不是查看您要实现的内容):您可以在任何尾部位置重复出现,并且if 的两个分支都处于尾部位置。您只需要在之前处理基本情况:

    (loop [a arg]
      (if (base-case? a)
        a
        (if (my-pred? a)
          (recur (frob a))
          (recur (whozzle a)))))
    

    您可能会通过为 recur 参数分支来表达这一点,但是(但它的工作原理相同):

    (loop [a arg]
      (if (base-case? a)
        a
        (recur (if (my-pred? a)
                 (frob a)
                 (whozzle a)))))
    

    【讨论】:

    • 谢谢,这有帮助,实际上我还想在 if 和 recur 两种情况下显示地图。
    【解决方案2】:

    不直接回答您的问题,但想提供一种不同的方法来解决问题:

    (->> [{:disease :Asthma :start 20 :end 41 :dose 0.25}
          {:disease :Asthma :start 31 :end 65 :dose 0.65}
          {:disease :BP :start 51 :end 91 :dose 0.75}]
    
         ;; EXPAND TO DATE SEQUENCE
         ;;
         (mapcat (fn [{:keys [start end] :as d}]
                   (let [x (dissoc d :start :end)]
                     (map (partial assoc x :dt) (range start end)))))
         (sort-by :dt)
    
         ;; ({:disease :Asthma, :dose 0.25, :dt 20}
         ;;  {:disease :Asthma, :dose 0.25, :dt 21}
         ;;  {:disease :Asthma, :dose 0.25, :dt 22}
    
         ;; 'GROUP' SUBSCRIPTIONS BY DATE
         ;;
         (partition-by :dt)
         (map #(reduce (fn [s e] (update s :subscriptions conj (dissoc e :dt)))
                       {:subscriptions #{}
                        :dt            (-> % first :dt)}
                      %))
         (partition-by :subscriptions)
    
         ;; (({:subscriptions #{{:disease :Asthma, :dose 0.25}}, :dt 20}
         ;;   ...
         ;;   {:subscriptions #{{:disease :Asthma, :dose 0.25}}, :dt 30})
         ;;  ({:subscriptions
         ;;    #{{:disease :Asthma, :dose 0.25} {:disease :Asthma, :dose 0.65}},
         ;;    :dt 31}
         ;;    ...
         ;;   {:subscriptions
         ;;    #{{:disease :Asthma, :dose 0.25} {:disease :Asthma, :dose 0.65}},
         ;;    :dt 40})
    
         ;; GET BACK DATE RANGE FROM PARTITIONS OF SUBSCRIPTIONS
         ;;
         (map #(-> %
                   first
                   (dissoc :dt)
                   (assoc :start (-> % first :dt)
                          :end (-> % last :dt))))
    
         ;; ({:subscriptions #{{:disease :Asthma, :dose 0.25}}, :start 20, :end 30}
         ;;  {:subscriptions
         ;;   #{{:disease :Asthma, :dose 0.25} {:disease :Asthma, :dose 0.65}},
         ;;   :start 31,
         ;;   :end 40}
    
    
         ;; FLATTEN THE LIST BY SUBSCRIPTIONS
         ;;
         (mapcat (fn [{:keys [subscriptions start end]}]
                   (map #(assoc % :start start :end end) subscriptions)))
         (sort-by (juxt :start :disease :dose)))
    
        ;; ({:disease :Asthma, :dose 0.25, :start 20, :end 30}
        ;;  {:disease :Asthma, :dose 0.25, :start 31, :end 40}
        ;;  {:disease :Asthma, :dose 0.65, :start 31, :end 40}
        ;;  {:disease :Asthma, :dose 0.65, :start 41, :end 50}
        ;;  {:disease :Asthma, :dose 0.65, :start 51, :end 64}
        ;;  {:disease :BP, :dose 0.75, :start 51, :end 64}
        ;;  {:disease :BP, :dose 0.75, :start 65, :end 90})
    
    
    • 为了便于阅读,我在这里使用整数作为日期

    【讨论】:

      猜你喜欢
      • 2019-05-02
      • 1970-01-01
      • 1970-01-01
      • 2014-04-30
      • 1970-01-01
      • 1970-01-01
      • 2013-11-13
      • 1970-01-01
      • 2015-08-10
      相关资源
      最近更新 更多